-
-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support css-modules #4405
Support css-modules #4405
Changes from 24 commits
7594e87
3ccf2bb
535d2b6
0441fc5
fefd86a
4a6fd1b
f40b98c
b12ffae
3f88f74
da0ad40
76a668f
39e2c3e
980f394
9719566
53004c4
41826b6
1753127
e1b73c7
5949b40
b2f9e66
950e2a6
2873911
cf34baa
6297d48
5f00d84
e2cf993
f42fb81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,12 +33,15 @@ | |
"@babel/runtime": "^7.1.2", | ||
"@emotion/styled": "^0.10.6", | ||
"@storybook/core": "4.0.0-rc.1", | ||
"@storybook/node-logger": "^3.4.11", | ||
"babel-plugin-react-docgen": "^2.0.0", | ||
"common-tags": "^1.8.0", | ||
"global": "^4.3.2", | ||
"lodash": "^4.17.11", | ||
"prop-types": "^15.6.2", | ||
"react-dev-utils": "^6.0.5" | ||
"react-dev-utils": "^6.0.5", | ||
"semver": "^5.6.0", | ||
"webpack": "^4.21.0" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤔 I wonder if we could make Webpack 4+ a peer dep instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
}, | ||
"peerDependencies": { | ||
"babel-loader": "^7.0.0 || ^8.0.0", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import semver from 'semver'; | ||
import { normalizeCondition } from 'webpack/lib/RuleSet'; | ||
|
||
let MiniCssExtractPlugin; | ||
|
||
export function isReactScriptsInstalled() { | ||
try { | ||
// eslint-disable-next-line global-require, import/no-extraneous-dependencies | ||
const reactScriptsJson = require('react-scripts/package.json'); | ||
if (semver.lt(reactScriptsJson.version, '2.0.0')) return false; | ||
|
||
// eslint-disable-next-line global-require, import/no-extraneous-dependencies | ||
MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. Do we need it as a dep? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need this as a dependency since we're first checking if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you can require it already in the |
||
return true; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
|
||
export function getStyleRules(rules) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd love to get some comments throughout this function. Not certain what's occurring. It looks like a way to concatenate across the subset of style loading possibilities given the array of file suffixes we're sifting? |
||
// Extensions of style rules we're interested in | ||
const extensions = ['.css', '.scss', '.sass', '.module.css', '.module.scss', '.module.sass']; | ||
|
||
return rules.reduce((styleRules, rule) => { | ||
if (rule.test && extensions.some(normalizeCondition(rule.test))) { | ||
// If the base test is for styles, return early | ||
return styleRules.concat(rule); | ||
} | ||
|
||
if (!rule.test && rule.oneOf) { | ||
styleRules.push(...getStyleRules(rule.oneOf)); | ||
} | ||
|
||
if (!rule.test && rule.rules) { | ||
styleRules.push(...getStyleRules(rule.rules)); | ||
} | ||
|
||
return styleRules; | ||
}, []); | ||
} | ||
|
||
export function getCraWebpackConfig(mode) { | ||
if (mode === 'production') { | ||
// eslint-disable-next-line global-require, import/no-extraneous-dependencies | ||
return require('react-scripts/config/webpack.config.prod'); | ||
} | ||
|
||
// eslint-disable-next-line global-require, import/no-extraneous-dependencies | ||
return require('react-scripts/config/webpack.config.dev'); | ||
} | ||
|
||
export function applyCRAWebpackConfig(baseConfig) { | ||
// Remove style rules from baseConfig | ||
const baseRulesExcludingStyles = baseConfig.module.rules.filter( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very nice 👏 |
||
rule => !rule.test || !['.css', '.scss', '.sass'].some(normalizeCondition(rule.test)) | ||
); | ||
|
||
// Load create-react-app config | ||
const craWebpackConfig = getCraWebpackConfig(baseConfig.mode); | ||
|
||
// Concat will ensure rules is an array | ||
const craStyleRules = getStyleRules([].concat(craWebpackConfig.module.rules)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could we not simply do:
Interested to hear more on "ensur[ing] rules is an array" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whoops. I was thinking |
||
|
||
// Add css minification for production | ||
const plugins = [...baseConfig.plugins]; | ||
if (baseConfig.mode === 'production') | ||
plugins.push( | ||
new MiniCssExtractPlugin({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really need this, though? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope! I just thought minification would be good for production. Also, if we don't want to include this plugin, then we have to filter out the related rule from all of the style rules. Adding the plugin was less work than removing it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this exclude interop for CRAv1? I don't really care about that, but it could be something to consider. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW we dont really need autoprefixer in the default ruleset either 🤷♂️ I'm a fan of good defaults 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kylemh This preset checks for |
||
// Options similar to the same options in webpackOptions.output | ||
// both options are optional | ||
filename: 'static/css/[name].[contenthash:8].css', | ||
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', | ||
}) | ||
); | ||
|
||
return { | ||
...baseConfig, | ||
module: { | ||
...baseConfig.module, | ||
rules: [...baseRulesExcludingStyles, ...craStyleRules], | ||
}, | ||
plugins, | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { logger } from '@storybook/node-logger'; | ||
import { applyCRAWebpackConfig, isReactScriptsInstalled } from './cra_config'; | ||
|
||
export function webpackFinal(config) { | ||
igor-dv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (!isReactScriptsInstalled()) { | ||
logger.info('=> Using base config because react-scripts is not installed.'); | ||
return config; | ||
} | ||
|
||
logger.info('=> Loading create-react-app config.'); | ||
|
||
return applyCRAWebpackConfig(config); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,24 +12,39 @@ function informAboutCustomConfig(defaultConfigName) { | |
logger.info(`=> Using default webpack setup based on "${defaultConfigName}".`); | ||
} | ||
|
||
export function webpack(config, { configDir, configType, defaultConfigName }) { | ||
function wrapPresets(presets) { | ||
return { | ||
webpackFinal: async (config, args) => presets.apply('webpackFinal', config, args), | ||
}; | ||
} | ||
|
||
async function createFinalDefaultConfig(presets, config, options) { | ||
const defaultConfig = createDefaultWebpackConfig(config); | ||
return presets.webpackFinal(defaultConfig, options); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
export async function webpack(config, options) { | ||
const { configDir, configType, defaultConfigName } = options; | ||
const presets = wrapPresets(options.presets); | ||
|
||
const finalConfig = await presets.webpackFinal(config, options); | ||
|
||
// Check whether user has a custom webpack config file and | ||
// return the (extended) base configuration if it's not available. | ||
const customConfig = loadCustomWebpackConfig(configDir); | ||
|
||
if (customConfig === null) { | ||
informAboutCustomConfig(defaultConfigName); | ||
return defaultConfig; | ||
return createFinalDefaultConfig(presets, config, options); | ||
} | ||
|
||
if (typeof customConfig === 'function') { | ||
logger.info('=> Loading custom webpack config (full-control mode).'); | ||
return customConfig(config, configType, defaultConfig); | ||
const finalDefaultConfig = await createFinalDefaultConfig(presets, config, options); | ||
return customConfig(finalConfig, configType, finalDefaultConfig); | ||
} | ||
|
||
logger.info('=> Loading custom webpack config (extending mode).'); | ||
|
||
return mergeConfigs(config, customConfig); | ||
return mergeConfigs(finalConfig, customConfig); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be
"4.0.0-rc.3"