diff --git a/src/cssModules.ts b/src/cssModules.ts index e95a27e91..b86987db4 100644 --- a/src/cssModules.ts +++ b/src/cssModules.ts @@ -1,3 +1,13 @@ +export function genInitCSSModulesCode() { + return ` +const cssModules = {} +const cssModulesStore = {} +const getCssModules = (name) => { + return Object.values(cssModulesStore[name]).reduce((acc, style) => Object.assign(acc, style), {}) +} +` +} + export function genCSSModulesCode( id: string, index: number, @@ -6,17 +16,24 @@ export function genCSSModulesCode( needsHotReload: boolean ): string { const styleVar = `style${index}` - let code = `\nimport ${styleVar} from ${request}` - // inject variable const name = typeof moduleName === 'string' ? moduleName : '$style' - code += `\ncssModules["${name}"] = ${styleVar}` + let code = ` +import ${styleVar} from ${request} + +if (!cssModulesStore["${name}"]) { + cssModulesStore["${name}"] = {} +} +cssModulesStore["${name}"]["${styleVar}"] = ${styleVar} +cssModules["${name}"] = getCssModules("${name}") +` if (needsHotReload) { code += ` if (module.hot) { module.hot.accept(${request}, () => { - cssModules["${name}"] = ${styleVar} + cssModulesStore["${name}"]["${styleVar}"] = ${styleVar} + cssModules["${name}"] = getCssModules("${name}") __VUE_HMR_RUNTIME__.rerender("${id}") }) }` diff --git a/src/index.ts b/src/index.ts index 890dc1cb3..1d3a00141 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ import type { } from 'vue/compiler-sfc' import { selectBlock } from './select' import { genHotReloadCode } from './hotReload' -import { genCSSModulesCode } from './cssModules' +import { genCSSModulesCode, genInitCSSModulesCode } from './cssModules' import { formatError } from './formatError' import VueLoaderPlugin from './plugin' @@ -273,7 +273,7 @@ export default function loader( ) } if (!hasCSSModules) { - stylesCode += `\nconst cssModules = {}` + stylesCode += genInitCSSModulesCode() propsToAttach.push([`__cssModules`, `cssModules`]) hasCSSModules = true } diff --git a/test/fixtures/css-modules-multiple.vue b/test/fixtures/css-modules-multiple.vue new file mode 100644 index 000000000..e99e9e445 --- /dev/null +++ b/test/fixtures/css-modules-multiple.vue @@ -0,0 +1,14 @@ + + + + diff --git a/test/style.spec.ts b/test/style.spec.ts index f208bb16c..d9dffd95e 100644 --- a/test/style.spec.ts +++ b/test/style.spec.ts @@ -204,6 +204,37 @@ test('CSS Modules Extend', async () => { expect(style).toContain(`.${escapedClassName} {\n color: #FF0000;\n}`) }) +test('Multiple CSS Modules', async () => { + const baseLoaders = [ + 'style-loader', + { + loader: 'css-loader', + options: { + modules: true, + }, + }, + ] + + const { instance } = await mockBundleAndRun({ + entry: 'css-modules-multiple.vue', + modify: (config: any) => { + config!.module!.rules = [ + { + test: /\.vue$/, + use: [DEFAULT_VUE_USE], + }, + { + test: /\.css$/, + use: baseLoaders, + }, + ] + }, + }) + + expect(instance.$style.red).toBeDefined() + expect(instance.$style.green).toBeDefined() +}) + test('v-bind() in CSS', async () => { const { window, instance } = await mockBundleAndRun({ entry: 'style-v-bind.vue',