diff --git a/README.md b/README.md index 8120dfeee801f..8177cd4c5a98b 100644 --- a/README.md +++ b/README.md @@ -391,7 +391,17 @@ if (process.env.NODE_ENV === 'production') { // Then in your {css} ``` +### CSS modules +[CSS modules](https://github.com/css-modules/css-modules) are support by default for all files with `.module.(css|less|scss|sass)` extension. + +```javascript +// Uses CSS Modules +import './my-component.module.css' + +// Doesn't use CSS Modules +import './main.css' +``` ### Configuring Babel diff --git a/lib/utils/webpack.config.js b/lib/utils/webpack.config.js index baa5402476d0c..cb47404661b97 100644 --- a/lib/utils/webpack.config.js +++ b/lib/utils/webpack.config.js @@ -122,6 +122,7 @@ module.exports = (program, directory, suppliedStage, webpackPort = 1500, routes }, __PREFIX_LINKS__: program.prefixLinks, }), + new ExtractTextPlugin('styles.css'), ] case 'build-javascript': return [ @@ -269,20 +270,43 @@ module.exports = (program, directory, suppliedStage, webpackPort = 1500, routes loader: 'file-loader', }) + const cssModulesConf = 'css?modules&importLoaders=1' + const cssModulesConfDev = + `${cssModulesConf}&sourceMap&localIdentName=[name]---[local]---[hash:base64:5]` + switch (stage) { case 'develop': + config.loader('css', { test: /\.css$/, + exclude: /\.module\.css$/, loaders: ['style', 'css', 'postcss'], }) config.loader('less', { test: /\.less/, + exclude: /\.module\.less$/, loaders: ['style', 'css', 'less'], }) config.loader('sass', { test: /\.(sass|scss)/, + exclude: /\.module\.(sass|scss)$/, loaders: ['style', 'css', 'sass'], }) + + // CSS modules + config.loader('cssModules', { + test: /\.module\.css$/, + loaders: ['style', cssModulesConfDev, 'postcss'], + }) + config.loader('lessModules', { + test: /\.module\.less/, + loaders: ['style', cssModulesConfDev, 'less'], + }) + config.loader('sassModules', { + test: /\.module\.(sass|scss)/, + loaders: ['style', cssModulesConfDev, 'sass'], + }) + config.merge({ postcss: [ require('postcss-import')(), @@ -296,16 +320,33 @@ module.exports = (program, directory, suppliedStage, webpackPort = 1500, routes case 'build-css': config.loader('css', { test: /\.css$/, + exclude: /\.module\.css$/, loader: ExtractTextPlugin.extract(['css', 'postcss']), }) config.loader('less', { test: /\.less/, + exclude: /\.module\.less$/, loader: ExtractTextPlugin.extract(['css', 'less']), }) config.loader('sass', { test: /\.(sass|scss)/, + exclude: /\.module\.(sass|scss)$/, loader: ExtractTextPlugin.extract(['css', 'sass']), }) + + // CSS modules + config.loader('cssModules', { + test: /\.module\.css$/, + loader: ExtractTextPlugin.extract('style', [cssModulesConf, 'postcss']), + }) + config.loader('lessModules', { + test: /\.module\.less/, + loader: ExtractTextPlugin.extract('style', [cssModulesConf, 'less']), + }) + config.loader('sassModules', { + test: /\.module\.(sass|scss)/, + loader: ExtractTextPlugin.extract('style', [cssModulesConf, 'sass']), + }) config.merge({ postcss: [ require('postcss-import')(), @@ -322,19 +363,37 @@ module.exports = (program, directory, suppliedStage, webpackPort = 1500, routes case 'build-html': // We don't deal with CSS at all when building the HTML. // The 'null' loader is used to prevent 'module not found' errors. + // On the other hand CSS modules loaders are necessary config.loader('css', { test: /\.css$/, + exclude: /\.module\.css$/, loader: 'null', }) config.loader('less', { test: /\.less/, + exclude: /\.module\.less$/, loader: 'null', }) config.loader('sass', { test: /\.(sass|scss)/, + exclude: /\.module\.(sass|scss)$/, loader: 'null', }) + + // CSS modules + config.loader('cssModules', { + test: /\.module\.css$/, + loader: ExtractTextPlugin.extract('style', [cssModulesConf, 'postcss']), + }) + config.loader('lessModules', { + test: /\.module\.less/, + loader: ExtractTextPlugin.extract('style', [cssModulesConf, 'less']), + }) + config.loader('sassModules', { + test: /\.module\.(sass|scss)/, + loader: ExtractTextPlugin.extract('style', [cssModulesConf, 'sass']), + }) return config case 'build-javascript':