diff --git a/playground/css/TestCssModules.vue b/playground/css/TestCssModules.vue
index 7491f01a472338..09b5624226a0b2 100644
--- a/playground/css/TestCssModules.vue
+++ b/playground/css/TestCssModules.vue
@@ -6,13 +6,17 @@
CSS modules import - this should be orange
+
+ SCSS modules import - this should be magenta
+
diff --git a/playground/css/testScssModules.module.scss b/playground/css/testScssModules.module.scss
new file mode 100644
index 00000000000000..8fd8bd8be44509
--- /dev/null
+++ b/playground/css/testScssModules.module.scss
@@ -0,0 +1,4 @@
+.magenta {
+ color: rgb(255, 0, 255);
+ }
+
\ No newline at end of file
diff --git a/src/node/build/buildPluginCss.ts b/src/node/build/buildPluginCss.ts
index cd17fb2c47052f..f356f3166c91f9 100644
--- a/src/node/build/buildPluginCss.ts
+++ b/src/node/build/buildPluginCss.ts
@@ -8,7 +8,8 @@ import {
compileCss,
cssPreprocessLangRE,
rewriteCssUrls,
- isCSSRequest
+ isCSSRequest,
+ cssModuleRE
} from '../utils/cssUtils'
import {
SFCStyleCompileResults,
@@ -60,7 +61,7 @@ export const createBuildCssPlugin = ({
source: css,
filename: id,
scoped: false,
- modules: id.endsWith('.module.css'),
+ modules: cssModuleRE.test(id),
preprocessLang: id.replace(
cssPreprocessLangRE,
'$2'
diff --git a/src/node/utils/cssUtils.ts b/src/node/utils/cssUtils.ts
index 4a6af76f3ec1ee..615836d98e71ea 100644
--- a/src/node/utils/cssUtils.ts
+++ b/src/node/utils/cssUtils.ts
@@ -12,6 +12,7 @@ import {
export const urlRE = /url\(\s*('[^']+'|"[^"]+"|[^'")]+)\s*\)/
export const cssPreprocessLangRE = /(.+)\.(less|sass|scss|styl|stylus|postcss)$/
+export const cssModuleRE = /(.+)\.module\.(less|sass|scss|styl|stylus|postcss|css)$/
export const isCSSRequest = (file: string) =>
file.endsWith('.css') || cssPreprocessLangRE.test(file)
diff --git a/test/test.js b/test/test.js
index 97b23d43518483..915b9558272845 100644
--- a/test/test.js
+++ b/test/test.js
@@ -435,6 +435,21 @@ describe('vite', () => {
}
})
+ test('import *.module.scss', async () => {
+ const el = await page.$('.scss-modules-import')
+ expect(await getComputedColor(el)).toBe('rgb(255, 0, 255)')
+ if (!isBuild) {
+ await updateFile('css/testScssModules.module.scss', (content) =>
+ content.replace('rgb(255, 0, 255)', 'rgb(0, 0, 2)')
+ )
+ // css module results in component reload so must use fresh selector
+ await expectByPolling(
+ () => getComputedColor('.scss-modules-import'),
+ 'rgb(0, 0, 2)'
+ )
+ }
+ })
+
test('pre-processors', async () => {
expect(await getText('.pug')).toMatch('template lang="pug"')
expect(await getComputedColor('.pug')).toBe('rgb(255, 0, 255)')