From eec08e46346d5f95ce60dfe4c0a7175c316b4267 Mon Sep 17 00:00:00 2001 From: Egor Blinov Date: Fri, 25 Jul 2025 00:23:25 +0200 Subject: [PATCH 1/2] feat: support multiple css-modules imports --- src/cssModules.ts | 25 +++++++++++++++---- src/index.ts | 4 ++-- test/fixtures/css-modules-multiple.vue | 14 +++++++++++ test/style.spec.ts | 33 ++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 test/fixtures/css-modules-multiple.vue 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..0c9897b93 100644 --- a/test/style.spec.ts +++ b/test/style.spec.ts @@ -204,6 +204,39 @@ 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, + }, + ] + }, + }) + + console.log(instance.$style) + + 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', From a2f36e9871cc0f77d6fc9d6ad2565f56e1d8a95a Mon Sep 17 00:00:00 2001 From: Egor Blinov Date: Fri, 25 Jul 2025 13:56:44 +0200 Subject: [PATCH 2/2] cleanup --- test/style.spec.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/style.spec.ts b/test/style.spec.ts index 0c9897b93..d9dffd95e 100644 --- a/test/style.spec.ts +++ b/test/style.spec.ts @@ -231,8 +231,6 @@ test('Multiple CSS Modules', async () => { }, }) - console.log(instance.$style) - expect(instance.$style.red).toBeDefined() expect(instance.$style.green).toBeDefined() }) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy