-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
feat: add static-style-extract #6713
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
tangjinzhou
merged 29 commits into
vueComponent:main
from
aibayanyu20:feat-extra-static-css
Aug 6, 2023
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
bd25c13
docs: add ant-design-vue nuxt module
aibayanyu20 b045c82
Merge branch 'vueComponent:feat-v4' into feat-v4
aibayanyu20 bc25663
Merge branch 'vueComponent:feat-v4' into feat-v4
aibayanyu20 d360f0f
feat: add static-style-extract
aibayanyu20 981f713
docs: fix import defineProps and defineEmits
aibayanyu20 d37aaae
feat: add static-style extract test
aibayanyu20 3f25a6d
fix: add ignore component
aibayanyu20 6b0946b
Merge branch 'vueComponent:feat-v4' into feat-v4
aibayanyu20 db95029
feat: calendar select support info.source param (#6697)
aibayanyu20 8434369
docs: synchronous config-provider demo (#6706)
selicens 1f1a8c7
revert: #6706
tangjinzhou e172c7b
feat: node error
aibayanyu20 f1e2d48
fix: Handle the output of styles in Server Side Rendering mode
aibayanyu20 92b51cb
fix: fix value required error
aibayanyu20 2bd5d85
chore: change tests dirname
aibayanyu20 d9aaa47
fix: auchor warning
aibayanyu20 1fd8deb
chore: add tests
aibayanyu20 d49c04c
chore: generate tests snap
aibayanyu20 0ec4eb1
docs: add ssr docs
aibayanyu20 5f9df5c
docs: synchronous config-provider demo (#6706)
selicens 0ec68c8
revert: #6706
tangjinzhou 50f9866
docs: add extract ssr doc
aibayanyu20 fb1e229
Merge branch 'feat-v4' into feat-extra-static-css
aibayanyu20 340b046
fix: Removing canUseDom does not have any effect.
aibayanyu20 f1c1432
fix: remove range picker in picker map
aibayanyu20 d9d6d8e
fix: watch source can only be a getter/effect function style warning
aibayanyu20 1a70c92
fix: styleContext props maybe ref
aibayanyu20 cfb298b
fix: remove black list component
aibayanyu20 592dea5
feat: add compChildNameMap
aibayanyu20 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
components/_util/static-style-extract/__tests__/__snapshots__/index.test.js.snap
Large diffs are not rendered by default.
Oops, something went wrong.
62 changes: 62 additions & 0 deletions
62
components/_util/static-style-extract/__tests__/index.test.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// import { StyleProvider } from '../../cssinjs'; | ||
import { extractStyle } from '../index'; | ||
import { ConfigProvider } from '../../../components'; | ||
|
||
const testGreenColor = '#008000'; | ||
describe('Static-Style-Extract', () => { | ||
it('should extract static styles', () => { | ||
const cssText = extractStyle(); | ||
expect(cssText).not.toContain(testGreenColor); | ||
expect(cssText).toMatchSnapshot(); | ||
}); | ||
it('should extract static styles with customTheme', () => { | ||
const cssText = extractStyle(node => { | ||
return ( | ||
<ConfigProvider | ||
theme={{ | ||
token: { | ||
colorPrimary: testGreenColor, | ||
}, | ||
}} | ||
> | ||
{node} | ||
</ConfigProvider> | ||
); | ||
}); | ||
expect(cssText).toContain(testGreenColor); | ||
expect(cssText).toMatchSnapshot(); | ||
}); | ||
// it('with custom hashPriority', () => { | ||
// const cssText = extractStyle( | ||
// (node) => ( | ||
// <StyleProvider hashPriority='high'> | ||
// <ConfigProvider | ||
// theme={{ | ||
// token: { | ||
// colorPrimary: testGreenColor, | ||
// }, | ||
// }} | ||
// > | ||
// {node} | ||
// </ConfigProvider> | ||
// </StyleProvider> | ||
// ), | ||
// ); | ||
// expect(cssText).toContain(testGreenColor); | ||
// expect(cssText).not.toContain(':where'); | ||
// expect(cssText).toMatchSnapshot(); | ||
// | ||
// const cssText2 = extractStyle((node) => ( | ||
// <ConfigProvider | ||
// theme={{ | ||
// token: { | ||
// colorPrimary: testGreenColor, | ||
// }, | ||
// }} | ||
// > | ||
// {node} | ||
// </ConfigProvider> | ||
// )); | ||
// expect(cssText2).toContain(':where'); | ||
// }); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { createCache, extractStyle as extStyle, StyleProvider } from '../cssinjs'; | ||
import * as antd from '../../components'; | ||
import { renderToString } from 'vue/server-renderer'; | ||
import type { CustomRender } from './interface'; | ||
const blackList: string[] = [ | ||
'ConfigProvider', | ||
'Grid', | ||
'Tour', | ||
'SelectOptGroup', | ||
'SelectOption', | ||
'MentionsOption', | ||
'TreeNode', | ||
'TreeSelectNode', | ||
'LocaleProvider', | ||
]; | ||
|
||
const pickerMap = { | ||
MonthPicker: 'month', | ||
WeekPicker: 'week', | ||
QuarterPicker: 'quarter', | ||
}; | ||
|
||
const compChildNameMap = { | ||
MenuDivider: 'Menu', | ||
MenuItem: 'Menu', | ||
MenuItemGroup: 'Menu', | ||
SubMenu: 'Menu', | ||
TableColumn: 'Table', | ||
TableColumnGroup: 'Table', | ||
TableSummary: 'Table', | ||
TableSummaryRow: 'Table', | ||
TableSummaryCell: 'Table', | ||
TabPane: 'Tabs', | ||
TimelineItem: 'Timeline', | ||
}; | ||
|
||
const defaultNode = () => ( | ||
<> | ||
{Object.keys(antd) | ||
.filter(name => !blackList.includes(name) && name[0] === name[0].toUpperCase()) | ||
.map(compName => { | ||
const Comp = antd[compName]; | ||
if (compName === 'Dropdown') { | ||
return ( | ||
<Comp key={compName} menu={{ items: [] }}> | ||
<div /> | ||
</Comp> | ||
); | ||
} | ||
if (compName === 'Anchor') { | ||
return <Comp key={compName} items={[]} />; | ||
} | ||
if (compName in pickerMap) { | ||
const Comp = antd['DatePicker']; | ||
const type = pickerMap[compName]; | ||
return <Comp key={compName} picker={type} />; | ||
} | ||
if (compName in compChildNameMap) { | ||
const ParentComp = antd[compChildNameMap[compName]]; | ||
return ( | ||
<ParentComp> | ||
<Comp /> | ||
</ParentComp> | ||
); | ||
} | ||
if (compName === 'QRCode' || compName === 'Segmented') { | ||
return ( | ||
<Comp key={compName} value={''}> | ||
<div /> | ||
</Comp> | ||
); | ||
} | ||
return <Comp key={compName} />; | ||
})} | ||
</> | ||
); | ||
|
||
export function extractStyle(customTheme?: CustomRender): string { | ||
const cache = createCache(); | ||
renderToString( | ||
<StyleProvider cache={cache}> | ||
{customTheme ? customTheme(defaultNode()) : defaultNode()} | ||
</StyleProvider>, | ||
); | ||
|
||
// Grab style from cache | ||
const styleText = extStyle(cache, true); | ||
|
||
return styleText; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import type { VueNode } from '../type'; | ||
|
||
export type CustomRender = (node: VueNode) => VueNode; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# SSR Static style export | ||
|
||
We are thinking about whether we can pre-bake the style of the component for front-end consumption like the v3 version, so we proposed [\[RFC\] Static Extract style](https://github.com/ant-design/ant-design/discussions/40985). Its idea is very simple that only need to render all the components once in advance to get the complete style from the cache, and then write it into the css file. | ||
|
||
```tsx | ||
const cache = createCache(); | ||
|
||
// HTML Content | ||
renderToString( | ||
<StyleProvider cache={cache}> | ||
<Button /> | ||
<Switch /> | ||
<Input /> | ||
{/* Rest antd components */} | ||
</StyleProvider>, | ||
); | ||
|
||
// Style Content | ||
const styleText = extractStyle(cache); | ||
``` | ||
|
||
Of course, this is a little cumbersome for developers. so we provide a method to fulfill this requirement: | ||
|
||
```tsx | ||
import { extractStyle } from 'ant-design-vue/lib/_util/static-style-extract'; | ||
import fs from 'fs'; | ||
|
||
// `extractStyle` containers all the antd component | ||
// excludes popup like component which is no need in ssr: Modal, message, notification, etc. | ||
const css = extractStyle(); | ||
|
||
fs.writeFile(...); | ||
``` | ||
|
||
If developers use a hybrid theme, they can also implement the hybrid requirements by themselves: | ||
|
||
```tsx | ||
// `node` is the components set we prepared | ||
const css = extractStyle(node => ( | ||
<> | ||
<ConfigProvider theme={theme1}>{node}</ConfigProvider> | ||
<ConfigProvider theme={theme2}>{node}</ConfigProvider> | ||
<ConfigProvider theme={theme3}>{node}</ConfigProvider> | ||
</> | ||
)); | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# SSR 静态样式导出 | ||
|
||
我们在思考是否可以如 v3 版本一样,预先烘焙组件的样式来使前端消费,所以提出了 [\[RFC\] Static Extract style](https://github.com/ant-design/ant-design/discussions/40985)。它的思路很简单,我们只需要提前将所有的组件进行一次渲染就可以从 cache 中获得完整的样式,然后将其写入到 css 文件中即可。 | ||
|
||
```tsx | ||
const cache = createCache(); | ||
|
||
// HTML Content | ||
renderToString( | ||
<StyleProvider cache={cache}> | ||
<Button /> | ||
<Switch /> | ||
<Input /> | ||
{/* Rest antd components */} | ||
</StyleProvider>, | ||
); | ||
|
||
// Style Content | ||
const styleText = extractStyle(cache); | ||
``` | ||
|
||
当然,这对于开发者而言稍微有点麻烦。所以我们提供了一个方法来实现该需求: | ||
|
||
```tsx | ||
import { extractStyle } from 'ant-design-vue/lib/_util/static-style-extract'; | ||
import fs from 'fs'; | ||
|
||
// `extractStyle` containers all the antd component | ||
// excludes popup like component which is no need in ssr: Modal, message, notification, etc. | ||
const css = extractStyle(); | ||
|
||
fs.writeFile(...); | ||
``` | ||
|
||
如果开发者使用了混合主题,也可以自行实现混合需求: | ||
|
||
```tsx | ||
// `node` is the components set we prepared | ||
const css = extractStyle(node => ( | ||
<> | ||
<ConfigProvider theme={theme1}>{node}</ConfigProvider> | ||
<ConfigProvider theme={theme2}>{node}</ConfigProvider> | ||
<ConfigProvider theme={theme3}>{node}</ConfigProvider> | ||
</> | ||
)); | ||
``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.