diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 106cd1bf379198e..d4e3106196e3c6e 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -897,6 +897,7 @@ export default async function getBaseWebpackConfig( hasSupportCss: !!config.experimental.css, hasSupportScss: !!config.experimental.scss, assetPrefix: config.assetPrefix || '', + sassOptions: config.experimental.sassOptions, }) if (typeof config.webpack === 'function') { diff --git a/packages/next/build/webpack/config/blocks/css/index.ts b/packages/next/build/webpack/config/blocks/css/index.ts index 0ba6ec7051db321..85989207bffb7a7 100644 --- a/packages/next/build/webpack/config/blocks/css/index.ts +++ b/packages/next/build/webpack/config/blocks/css/index.ts @@ -43,6 +43,7 @@ export const css = curry(async function css( // Source maps are required so that `resolve-url-loader` can locate // files original to their source directory. sourceMap: true, + sassOptions: ctx.sassOptions, }, }, // Then, `sass-loader` will have passed-through CSS imports as-is instead diff --git a/packages/next/build/webpack/config/index.ts b/packages/next/build/webpack/config/index.ts index 8df1fffe08efa9b..914b8f47e745e3c 100644 --- a/packages/next/build/webpack/config/index.ts +++ b/packages/next/build/webpack/config/index.ts @@ -13,6 +13,7 @@ export async function build( hasSupportCss, hasSupportScss, assetPrefix, + sassOptions, }: { rootDirectory: string customAppFile: string | null @@ -21,6 +22,7 @@ export async function build( hasSupportCss: boolean hasSupportScss: boolean assetPrefix: string + sassOptions: any } ): Promise { const ctx: ConfigurationContext = { @@ -35,6 +37,7 @@ export async function build( ? assetPrefix.slice(0, -1) : assetPrefix : '', + sassOptions, } const fn = pipe(base(ctx), css(hasSupportCss, hasSupportScss, ctx)) diff --git a/packages/next/build/webpack/config/utils.ts b/packages/next/build/webpack/config/utils.ts index f84d9e903dec439..757ee4bc9b7b374 100644 --- a/packages/next/build/webpack/config/utils.ts +++ b/packages/next/build/webpack/config/utils.ts @@ -11,6 +11,8 @@ export type ConfigurationContext = { isClient: boolean assetPrefix: string + + sassOptions: any } export type ConfigurationFn = ( diff --git a/packages/next/next-server/server/config.ts b/packages/next/next-server/server/config.ts index 84cfe126c923bc2..2535ec0ac8e970e 100644 --- a/packages/next/next-server/server/config.ts +++ b/packages/next/next-server/server/config.ts @@ -52,6 +52,7 @@ const defaultConfig: { [key: string]: any } = { reactMode: 'legacy', workerThreads: false, basePath: '', + sassOptions: {}, }, future: { excludeDefaultMomentLocales: false, diff --git a/test/integration/scss-fixtures/basic-module-include-paths/next.config.js b/test/integration/scss-fixtures/basic-module-include-paths/next.config.js new file mode 100644 index 000000000000000..e8abbc26eb6c576 --- /dev/null +++ b/test/integration/scss-fixtures/basic-module-include-paths/next.config.js @@ -0,0 +1,9 @@ +const path = require('path') + +module.exports = { + experimental: { + sassOptions: { + includePaths: [path.join(__dirname, 'styles')], + }, + }, +} diff --git a/test/integration/scss-fixtures/basic-module-include-paths/pages/index.js b/test/integration/scss-fixtures/basic-module-include-paths/pages/index.js new file mode 100644 index 000000000000000..7b42859a67e323c --- /dev/null +++ b/test/integration/scss-fixtures/basic-module-include-paths/pages/index.js @@ -0,0 +1,9 @@ +import { redText } from './index.module.scss' + +export default function Home() { + return ( +
+ This text should be red. +
+ ) +} diff --git a/test/integration/scss-fixtures/basic-module-include-paths/pages/index.module.scss b/test/integration/scss-fixtures/basic-module-include-paths/pages/index.module.scss new file mode 100644 index 000000000000000..a03f5a3efebaca2 --- /dev/null +++ b/test/integration/scss-fixtures/basic-module-include-paths/pages/index.module.scss @@ -0,0 +1,5 @@ +@import '_vars.scss'; + +.redText { + color: $var; +} diff --git a/test/integration/scss-fixtures/basic-module-include-paths/styles/_vars.scss b/test/integration/scss-fixtures/basic-module-include-paths/styles/_vars.scss new file mode 100644 index 000000000000000..121e9ffac316458 --- /dev/null +++ b/test/integration/scss-fixtures/basic-module-include-paths/styles/_vars.scss @@ -0,0 +1 @@ +$var: red; diff --git a/test/integration/scss/test/index.test.js b/test/integration/scss/test/index.test.js index 9daec89617a4358..7c6203a7a55d6aa 100644 --- a/test/integration/scss/test/index.test.js +++ b/test/integration/scss/test/index.test.js @@ -78,6 +78,34 @@ describe('SCSS Support', () => { }) }) + describe('Basic Module Include Paths Support', () => { + const appDir = join(fixturesDir, 'basic-module-include-paths') + + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) + + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) + }) + + it(`should've emitted a single CSS file`, async () => { + const cssFolder = join(appDir, '.next/static/css') + + const files = await readdir(cssFolder) + const cssFiles = files.filter(f => /\.css$/.test(f)) + + expect(cssFiles.length).toBe(1) + expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain( + 'color:red' + ) + }) + }) + describe('Basic Global Support with src/ dir', () => { const appDir = join(fixturesDir, 'single-global-src')