Skip to content

Commit 8525fc9

Browse files
authored
Merge pull request #36 from markthree/main
feat: add extractStyle
2 parents 7c43723 + 48db824 commit 8525fc9

File tree

7 files changed

+143
-74
lines changed

7 files changed

+143
-74
lines changed

Diff for: README.md

+18
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,24 @@ If you wish to add automatically import content from Ant Design Vue, you can add
9999
If there are components that are not imported automatically from @ant-design/icons-vue, you need to add the component name here.
100100

101101

102+
### extractStyle
103+
104+
* Type: `boolean`
105+
106+
> Solve page css flicker problem
107+
108+
Extracts and injects css on demand, defaults to false
109+
110+
```vue
111+
<!-- If the extractStyle option is enabled, we can use a-extract-style on the outermost level of the template in app.vue -->
112+
<template>
113+
<a-extract-style>
114+
<!-- Your page or component -->
115+
</a-extract-style>
116+
</template>
117+
```
118+
119+
102120
## Development
103121

104122
```bash

Diff for: playground/app.vue

+73-71
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,83 @@
11
<template>
2-
<a-config-provider :theme="theme">
3-
<div class="container">
4-
<div>
2+
<a-extract-style>
3+
<a-config-provider :theme="theme">
4+
<div class="container">
5+
<div>
6+
<a-space>
7+
<a-button @click="changeTheme('dark')">
8+
dark
9+
</a-button>
10+
<a-button @click="changeTheme('light')">
11+
light
12+
</a-button>
13+
</a-space>
14+
</div>
15+
<a-alert
16+
message="Success Text"
17+
type="success"
18+
/>
19+
<div>
20+
icon:
21+
<AlertFilled />
22+
<LoadingOutlined />
23+
</div>
24+
<a-table v-bind="tableProps" />
525
<a-space>
6-
<a-button @click="changeTheme('dark')">
7-
dark
26+
<a-button
27+
type="primary"
28+
@click="handleMessage('success')"
29+
>
30+
message success
831
</a-button>
9-
<a-button @click="changeTheme('light')">
10-
light
32+
<a-button @click="handleMessage('info')">
33+
message info
1134
</a-button>
1235
</a-space>
13-
</div>
14-
<a-alert
15-
message="Success Text"
16-
type="success"
17-
/>
18-
<div>
19-
icon:
20-
<AlertFilled />
21-
<LoadingOutlined />
22-
</div>
23-
<a-table v-bind="tableProps" />
24-
<a-space>
25-
<a-button
26-
type="primary"
27-
@click="handleMessage('success')"
28-
>
29-
message success
30-
</a-button>
31-
<a-button @click="handleMessage('info')">
32-
message info
33-
</a-button>
34-
</a-space>
35-
<a-space>
36-
<a-button
37-
type="primary"
38-
@click="handleModal('success')"
39-
>
40-
modal success
41-
</a-button>
42-
<a-button @click="handleModal('info')">
43-
modal info
44-
</a-button>
45-
</a-space>
46-
<a-space>
47-
<a-button
48-
type="primary"
49-
@click="handleNotification('success')"
36+
<a-space>
37+
<a-button
38+
type="primary"
39+
@click="handleModal('success')"
40+
>
41+
modal success
42+
</a-button>
43+
<a-button @click="handleModal('info')">
44+
modal info
45+
</a-button>
46+
</a-space>
47+
<a-space>
48+
<a-button
49+
type="primary"
50+
@click="handleNotification('success')"
51+
>
52+
notification success
53+
</a-button>
54+
<a-button @click="handleNotification('info')">
55+
notification info
56+
</a-button>
57+
</a-space>
58+
<a-flex
59+
gap="middle"
60+
vertical
5061
>
51-
notification success
52-
</a-button>
53-
<a-button @click="handleNotification('info')">
54-
notification info
55-
</a-button>
56-
</a-space>
57-
<a-flex
58-
gap="middle"
59-
vertical
60-
>
61-
<a-radio-group v-model:value="value">
62-
<a-radio value="horizontal">
63-
horizontal
64-
</a-radio>
65-
<a-radio value="vertical">
66-
vertical
67-
</a-radio>
68-
</a-radio-group>
69-
<a-flex :vertical="value === 'vertical'">
70-
<div
71-
v-for="(item, index) in new Array(4)"
72-
:key="item"
73-
:style="{ ...baseStyle, background: `${index % 2 ? '#1677ff' : '#1677ffbf'}` }"
74-
/>
62+
<a-radio-group v-model:value="value">
63+
<a-radio value="horizontal">
64+
horizontal
65+
</a-radio>
66+
<a-radio value="vertical">
67+
vertical
68+
</a-radio>
69+
</a-radio-group>
70+
<a-flex :vertical="value === 'vertical'">
71+
<div
72+
v-for="(item, index) in new Array(4)"
73+
:key="item"
74+
:style="{ ...baseStyle, background: `${index % 2 ? '#1677ff' : '#1677ffbf'}` }"
75+
/>
76+
</a-flex>
7577
</a-flex>
76-
</a-flex>
77-
</div>
78-
</a-config-provider>
78+
</div>
79+
</a-config-provider>
80+
</a-extract-style>
7981
</template>
8082

8183
<script setup lang="ts">

Diff for: playground/nuxt.config.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
export default defineNuxtConfig({
22
modules: ['../src/module'],
3-
antd: {},
3+
antd: {
4+
extractStyle: true
5+
},
46
imports:{
57
autoImport:true
68
},

Diff for: src/config.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ export { allComponents } from "./antdv"
1414
export const defaults:Options = {
1515
components: allComponents,
1616
icons: allIcons,
17-
imports: allImports
17+
imports: allImports,
18+
extractStyle: false
1819
}

Diff for: src/module.ts

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { defineNuxtModule } from '@nuxt/kit'
1+
import { addComponent, createResolver, defineNuxtModule, useNuxt } from '@nuxt/kit'
22
import { libraryName,defaults } from "./config"
33
import { resolveComponents,resolveImports } from "./core"
44
import type { Options } from './types'
@@ -18,9 +18,33 @@ export default defineNuxtModule<Partial<Options>>({
1818
nuxt.options.imports.autoImport !== false && resolveImports(options)
1919
nuxt.options.components !== false && resolveComponents(options)
2020

21+
if (options.extractStyle) {
22+
extractStyle()
23+
}
2124

2225
// const resolver = createResolver(import.meta.url)
2326
// Do not add the extension since the `.ts` will be transpiled to `.mjs` after `npm run prepack`
2427
// addPlugin(resolver.resolve('./runtime/plugin'))
2528
}
2629
})
30+
31+
function extractStyle() {
32+
const nuxt = useNuxt()
33+
// The spa does not need to be injected with css.
34+
if (!nuxt.options.ssr) {
35+
return;
36+
}
37+
// When generating, replace process.env.NODE_ENV to production (defaults to prerender).
38+
// And antd relies on process.env.NODE_ENV when generating css prefixes.
39+
if (nuxt.options.dev === false && nuxt.options.nitro.static) {
40+
nuxt.options.nitro.replace ??= {};
41+
nuxt.options.nitro.replace["process.env.NODE_ENV"] = "'production'";
42+
}
43+
44+
// Adding auxiliary components
45+
const resolver = createResolver(import.meta.url)
46+
addComponent({
47+
name: 'AExtractStyle',
48+
filePath: resolver.resolve('./runtime/components/AExtractStyle.vue')
49+
})
50+
}

Diff for: src/runtime/components/AExtractStyle.vue

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script lang="ts" setup>
2+
import { createCache, extractStyle, StyleProvider } from "ant-design-vue"
3+
4+
const cache = createCache()
5+
6+
const app = useNuxtApp()
7+
8+
// Real-time style extraction at ssr
9+
// Pre-rendered extraction styles for ssg
10+
app.hook('app:rendered', () => {
11+
useHead({
12+
style: [extractStyle(cache, true)]
13+
})
14+
})
15+
</script>
16+
17+
<template>
18+
<StyleProvider :cache="cache">
19+
<slot />
20+
</StyleProvider>
21+
</template>

Diff for: src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export interface Options {
55
icons: false | PresetImport[]
66
components: false | PresetImport[]
77
imports: PresetImport[]
8+
extractStyle: boolean
89
}
910

1011

0 commit comments

Comments
 (0)