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',