Skip to content

Commit 3fb4118

Browse files
authoredJan 21, 2022
fix(plugin-vue): make cssm code tree shakeable (#6353)
1 parent 6e98ff2 commit 3fb4118

File tree

12 files changed

+143
-12
lines changed

12 files changed

+143
-12
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @ts-check
2+
// this is automtically detected by scripts/jestPerTestSetup.ts and will replace
3+
// the default e2e test serve behavior
4+
5+
exports.serve = async function serve() {
6+
// do nothing, skip default behavior
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { build } from 'vite'
2+
import path from 'path'
3+
import type { OutputChunk, RollupOutput } from 'rollup'
4+
5+
describe('vue component library', () => {
6+
test('should output tree shakeable css module code', async () => {
7+
// Build lib
8+
await build({
9+
logLevel: 'silent',
10+
configFile: path.resolve(__dirname, '../vite.config.lib.ts')
11+
})
12+
// Build app
13+
const { output } = (await build({
14+
logLevel: 'silent',
15+
configFile: path.resolve(__dirname, '../vite.config.consumer.ts')
16+
})) as RollupOutput
17+
const { code } = output.find(
18+
(e) => e.type === 'chunk' && e.isEntry
19+
) as OutputChunk
20+
// Unused css module should be treeshaked
21+
expect(code).toContain('styleA') // styleA is used by CompA
22+
expect(code).not.toContain('styleB') // styleB is not used
23+
})
24+
})
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<html>
2+
<body>
3+
<div id="app"></div>
4+
<script type="module" src="./src-consumer/index.ts"></script>
5+
</body>
6+
</html>
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "test-vue-lib",
3+
"private": true,
4+
"version": "0.0.0",
5+
"scripts": {
6+
"dev-consumer": "vite --config ./vite.config.consumer.ts",
7+
"build-lib": "vite build --config ./vite.config.lib.ts",
8+
"build-consumer": "vite build --config ./vite.config.consumer.ts"
9+
},
10+
"dependencies": {
11+
"vue": "^3.2.25"
12+
},
13+
"devDependencies": {
14+
"@vitejs/plugin-vue": "workspace:*"
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @ts-ignore
2+
/* eslint-disable node/no-missing-import */
3+
import { CompA } from '../dist/lib/my-vue-lib.es'
4+
import '../dist/lib/style.css'
5+
import { createApp } from 'vue'
6+
7+
const app = createApp(CompA)
8+
app.mount('#app')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<template>
2+
<div :class="$style.styleA">CompA</div>
3+
</template>
4+
<style module>
5+
.styleA {
6+
color: red;
7+
}
8+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<template>
2+
<div :class="$style.styleB">CompB</div>
3+
</template>
4+
<style module>
5+
.styleB {
6+
color: blue;
7+
}
8+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as CompA } from './CompA.vue'
2+
export { default as CompB } from './CompB.vue'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { defineConfig } from 'vite'
2+
import vue from '@vitejs/plugin-vue'
3+
4+
export default defineConfig({
5+
root: __dirname,
6+
build: {
7+
outDir: 'dist/consumer'
8+
},
9+
plugins: [vue()]
10+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import path from 'path'
2+
import { defineConfig } from 'vite'
3+
import vue from '@vitejs/plugin-vue'
4+
5+
export default defineConfig({
6+
root: __dirname,
7+
build: {
8+
outDir: 'dist/lib',
9+
lib: {
10+
entry: path.resolve(__dirname, 'src-lib/index.ts'),
11+
name: 'MyVueLib',
12+
formats: ['es'],
13+
fileName: (format) => `my-vue-lib.${format}.js`
14+
},
15+
rollupOptions: {
16+
external: ['vue'],
17+
output: {
18+
globals: { vue: 'Vue' }
19+
}
20+
}
21+
},
22+
plugins: [vue()]
23+
})

‎packages/plugin-vue/src/main.ts

+22-12
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ async function genStyleCode(
299299
attachedProps: [string, string][]
300300
) {
301301
let stylesCode = ``
302-
let hasCSSModules = false
302+
let cssModulesMap: Record<string, string> | undefined
303303
if (descriptor.styles.length) {
304304
for (let i = 0; i < descriptor.styles.length; i++) {
305305
const style = descriptor.styles[i]
@@ -320,12 +320,13 @@ async function genStyleCode(
320320
`<style module> is not supported in custom elements mode.`
321321
)
322322
}
323-
if (!hasCSSModules) {
324-
stylesCode += `\nconst cssModules = {}`
325-
attachedProps.push([`__cssModules`, `cssModules`])
326-
hasCSSModules = true
327-
}
328-
stylesCode += genCSSModulesCode(i, styleRequest, style.module)
323+
const [importCode, nameMap] = genCSSModulesCode(
324+
i,
325+
styleRequest,
326+
style.module
327+
)
328+
stylesCode += importCode
329+
Object.assign((cssModulesMap ||= {}), nameMap)
329330
} else {
330331
if (asCustomElement) {
331332
stylesCode += `\nimport _style_${i} from ${JSON.stringify(
@@ -344,22 +345,31 @@ async function genStyleCode(
344345
])
345346
}
346347
}
348+
if (cssModulesMap) {
349+
const mappingCode =
350+
Object.entries(cssModulesMap).reduce(
351+
(code, [key, value]) => code + `"${key}":${value},\n`,
352+
'{\n'
353+
) + '}'
354+
stylesCode += `\nconst cssModules = ${mappingCode}`
355+
attachedProps.push([`__cssModules`, `cssModules`])
356+
}
347357
return stylesCode
348358
}
349359

350360
function genCSSModulesCode(
351361
index: number,
352362
request: string,
353363
moduleName: string | boolean
354-
): string {
364+
): [importCode: string, nameMap: Record<string, string>] {
355365
const styleVar = `style${index}`
356366
const exposedName = typeof moduleName === 'string' ? moduleName : '$style'
357367
// inject `.module` before extension so vite handles it as css module
358368
const moduleRequest = request.replace(/\.(\w+)$/, '.module.$1')
359-
return (
360-
`\nimport ${styleVar} from ${JSON.stringify(moduleRequest)}` +
361-
`\ncssModules["${exposedName}"] = ${styleVar}`
362-
)
369+
return [
370+
`\nimport ${styleVar} from ${JSON.stringify(moduleRequest)}`,
371+
{ [exposedName]: styleVar }
372+
]
363373
}
364374

365375
async function genCustomBlockCode(

‎pnpm-lock.yaml

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.