From ca795afab77da3caa195141a010c393cca5c4042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Stani=C3=B3w?= Date: Fri, 2 Jul 2021 17:45:37 +0100 Subject: [PATCH] feat: Support CSS Modules --- src/index.test.js | 14 ++++++------ src/index.ts | 55 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/index.test.js b/src/index.test.js index d23c2b3..dd2793a 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -1,5 +1,5 @@ import { logger } from '@storybook/node-logger'; -import { webpack } from './index.ts'; +import { webpackFinal } from './index.ts'; jest.mock('@storybook/node-logger'); @@ -24,14 +24,14 @@ describe('webpack hook', () => { rules: ['dummy-loader'], }, }; - const config = webpack(configFixture); + const config = webpackFinal(configFixture); expect(config.module.rules[0]).toEqual('dummy-loader'); expect(config.module.rules[1]).toMatchObject(loaderMatcher); }); test('applying to an empty webpack config', () => { const configFixture = {}; - const config = webpack(configFixture); + const config = webpackFinal(configFixture); expect(config.module.rules[0]).toMatchObject(loaderMatcher); }); @@ -39,7 +39,7 @@ describe('webpack hook', () => { const version = '99.99.99'; const configFixture = {}; const fakePostcss = () => ({ version }); - const config = webpack(configFixture, { + const config = webpackFinal(configFixture, { postcssLoaderOptions: { implementation: fakePostcss, }, @@ -61,7 +61,7 @@ describe('webpack hook', () => { test('always ensures importLoaders: 1 on css-loader', () => { const configFixture = {}; - const config = webpack(configFixture, { + const config = webpackFinal(configFixture, { cssLoaderOptions: { importLoaders: 2, }, @@ -80,7 +80,7 @@ describe('webpack hook', () => { test('disables all loaders if their options are set to false', () => { const configFixture = {}; - const config = webpack(configFixture, { + const config = webpackFinal(configFixture, { styleLoaderOptions: false, cssLoaderOptions: false, postcssLoaderOptions: false, @@ -92,7 +92,7 @@ describe('webpack hook', () => { test('overrides rule properties with option', () => { const configFixture = {}; - const config = webpack(configFixture, { + const config = webpackFinal(configFixture, { rule: { sideEffects: false, }, diff --git a/src/index.ts b/src/index.ts index 1f671dd..e0f3d8a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -33,7 +33,7 @@ function wrapLoader( return [{ loader, options }]; } -export const webpack = ( +export const webpackFinal = ( webpackConfig: Configuration = {}, options: Options = {}, ): Configuration => { @@ -57,26 +57,47 @@ export const webpack = ( logger.info(`=> Using PostCSS preset with postcss@${version}`); + const { rules = [] } = webpackConfig.module || {}; + + const prevCssRuleIdx = rules.findIndex( + ({ test }) => test?.toString() === '/\\.css$/', + ); + const cssRuleIdx = prevCssRuleIdx === -1 ? rules.length : prevCssRuleIdx; + const rulesBefore = rules.slice(0, cssRuleIdx); + const rulesAfter = rules.slice(cssRuleIdx + 1); + + const cssRule = { + test: /\.css$/, + sideEffects: true, + exclude: /\.module\.css$/, + ...rule, + use: [ + ...wrapLoader(require.resolve('style-loader'), styleLoaderOptions), + ...wrapLoader(require.resolve('css-loader'), cssLoaderOptions), + ...wrapLoader(require.resolve('postcss-loader'), postcssLoaderOptions), + ], + }; + + const cssModulesRule = { + test: /\.css$/, + include: /\.module\.css$/, + sideEffects: true, + ...rule, + use: [ + ...wrapLoader(require.resolve('style-loader'), styleLoaderOptions), + ...wrapLoader(require.resolve('css-loader'), { + ...cssLoaderOptions, + modules: true, + }), + ...wrapLoader(require.resolve('postcss-loader'), postcssLoaderOptions), + ], + }; + return { ...webpackConfig, module: { ...webpackConfig.module, - rules: [ - ...(webpackConfig.module?.rules ?? []), - { - test: /\.css$/, - sideEffects: true, - ...rule, - use: [ - ...wrapLoader(require.resolve('style-loader'), styleLoaderOptions), - ...wrapLoader(require.resolve('css-loader'), cssLoaderOptions), - ...wrapLoader( - require.resolve('postcss-loader'), - postcssLoaderOptions, - ), - ], - }, - ], + rules: [...rulesBefore, cssRule, cssModulesRule, ...rulesAfter], }, }; };