From a610276cf81967025ecedb284a43d591bd6b32a0 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Thu, 12 Jan 2023 17:58:58 -0500 Subject: [PATCH] fix(webpack): fix loader config for global styles (#14323) --- e2e/react/src/react.test.ts | 11 +++ packages/webpack/src/utils/with-web.ts | 111 ++++++++++++++++++++----- 2 files changed, 100 insertions(+), 22 deletions(-) diff --git a/e2e/react/src/react.test.ts b/e2e/react/src/react.test.ts index 671fa16c3ae28..96f2e1a78c9ba 100644 --- a/e2e/react/src/react.test.ts +++ b/e2e/react/src/react.test.ts @@ -50,6 +50,17 @@ describe('React Applications', () => { ` ); + // Make sure global stylesheets are properly processed. + const stylesPath = `apps/${appName}/src/styles.css`; + updateFile( + stylesPath, + ` + .foobar { + background-image: url('/bg.png'); + } + ` + ); + const libTestResults = await runCLIAsync(`test ${libName}`); expect(libTestResults.combinedOutput).toContain( 'Test Suites: 1 passed, 1 total' diff --git a/packages/webpack/src/utils/with-web.ts b/packages/webpack/src/utils/with-web.ts index 586891251038d..1ba8654b21abd 100644 --- a/packages/webpack/src/utils/with-web.ts +++ b/packages/webpack/src/utils/with-web.ts @@ -108,10 +108,12 @@ export function withWeb() { const cssModuleRules: RuleSetRule[] = [ { test: /\.module\.css$/, + exclude: globalStylePaths, use: getCommonLoadersForCssModules(options, includePaths), }, { test: /\.module\.(scss|sass)$/, + exclude: globalStylePaths, use: [ ...getCommonLoadersForCssModules(options, includePaths), { @@ -129,6 +131,7 @@ export function withWeb() { }, { test: /\.module\.less$/, + exclude: globalStylePaths, use: [ ...getCommonLoadersForCssModules(options, includePaths), { @@ -143,6 +146,7 @@ export function withWeb() { }, { test: /\.module\.styl$/, + exclude: globalStylePaths, use: [ ...getCommonLoadersForCssModules(options, includePaths), { @@ -160,10 +164,12 @@ export function withWeb() { const globalCssRules: RuleSetRule[] = [ { test: /\.css$/, + exclude: globalStylePaths, use: getCommonLoadersForGlobalCss(options, includePaths), }, { test: /\.scss$|\.sass$/, + exclude: globalStylePaths, use: [ ...getCommonLoadersForGlobalCss(options, includePaths), { @@ -183,6 +189,7 @@ export function withWeb() { }, { test: /\.less$/, + exclude: globalStylePaths, use: [ ...getCommonLoadersForGlobalCss(options, includePaths), { @@ -199,6 +206,7 @@ export function withWeb() { }, { test: /\.styl$/, + exclude: globalStylePaths, use: [ ...getCommonLoadersForGlobalCss(options, includePaths), { @@ -214,33 +222,72 @@ export function withWeb() { }, ]; - const rules: RuleSetRule[] = [ + const globalStyleRules: RuleSetRule[] = [ { - test: /\.css$|\.scss$|\.sass$|\.less$|\.styl$/, - oneOf: [ - ...cssModuleRules, - ...globalCssRules, - // load global css as css files + test: /\.css$/, + include: globalStylePaths, + use: getCommonLoadersForGlobalStyle(options, includePaths), + }, + { + test: /\.scss$|\.sass$/, + include: globalStylePaths, + use: [ + ...getCommonLoadersForGlobalStyle(options, includePaths), { - test: /\.css$|\.scss$|\.sass$|\.less$|\.styl$/, - include: globalStylePaths, - use: [ - { - loader: MiniCssExtractPlugin.loader, - options: { esModule: true }, + loader: require.resolve('sass-loader'), + options: { + implementation: require('sass'), + sourceMap: options.sourceMap, + sassOptions: { + fiber: false, + // bootstrap-sass requires a minimum precision of 8 + precision: 8, + includePaths, }, - { loader: require.resolve('css-loader') }, - { - loader: require.resolve('postcss-loader'), - options: { - implementation: require('postcss'), - postcssOptions: postcssOptionsCreator(options, includePaths), - }, + }, + }, + ], + }, + { + test: /\.less$/, + include: globalStylePaths, + use: [ + ...getCommonLoadersForGlobalStyle(options, includePaths), + { + loader: require.resolve('less-loader'), + options: { + sourceMap: options.sourceMap, + lessOptions: { + javascriptEnabled: true, + ...lessPathOptions, }, - ], + }, }, ], }, + { + test: /\.styl$/, + include: globalStylePaths, + use: [ + ...getCommonLoadersForGlobalStyle(options, includePaths), + { + loader: require.resolve('stylus-loader'), + options: { + sourceMap: options.sourceMap, + stylusOptions: { + include: includePaths, + }, + }, + }, + ], + }, + ]; + + const rules: RuleSetRule[] = [ + { + test: /\.css$|\.scss$|\.sass$|\.less$|\.styl$/, + oneOf: [...cssModuleRules, ...globalCssRules, ...globalStyleRules], + }, ]; plugins.push( @@ -305,7 +352,6 @@ export function withWeb() { ...config.module, rules: [ ...(config.module.rules ?? []), - ...rules, { test: /\.(bmp|png|jpe?g|gif|webp|avif)$/, type: 'asset', @@ -322,6 +368,7 @@ export function withWeb() { name: `[name]${hashFormat.file}.[ext]`, }, }, + ...rules, ], }; processed.add(config); @@ -421,7 +468,27 @@ function getCommonLoadersForGlobalCss( ? MiniCssExtractPlugin.loader : require.resolve('style-loader'), }, - { loader: require.resolve('css-loader') }, + { loader: require.resolve('css-loader'), options: { url: false } }, + { + loader: require.resolve('postcss-loader'), + options: { + implementation: require('postcss'), + postcssOptions: postcssOptionsCreator(options, includePaths), + }, + }, + ]; +} + +function getCommonLoadersForGlobalStyle( + options: NormalizedWebpackExecutorOptions, + includePaths: string[] +) { + return [ + { + loader: MiniCssExtractPlugin.loader, + options: { esModule: true }, + }, + { loader: require.resolve('css-loader'), options: { url: false } }, { loader: require.resolve('postcss-loader'), options: {