Skip to content

Commit

Permalink
Add support for CSS Modules with explicit filename (#2285)
Browse files Browse the repository at this point in the history
* Add css modules with [name].modules.css file convention

* Add e2e for CSS Modules

* Updated based on feedback

* Change css modules class name to be deterministic and fix licences

* Update css modules class naming convention
  • Loading branch information
ro-savage authored and rubenbp committed Jan 29, 2018
1 parent d932ab1 commit e87e139
Show file tree
Hide file tree
Showing 10 changed files with 304 additions and 107 deletions.
86 changes: 54 additions & 32 deletions packages/react-scripts/config/webpack.config.dev.js
Expand Up @@ -30,6 +30,20 @@ const publicUrl = '';
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);

// Options for PostCSS as we reference these options twice
// Adds vendor prefixing to support IE9 and above
const postCSSLoaderOptions = {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
flexbox: 'no-2009',
}),
],
};

// This is the development configuration.
// It is focused on developer experience and fast rebuilds.
// The production configuration is different and lives in a separate file.
Expand Down Expand Up @@ -123,7 +137,7 @@ module.exports = {
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
new TsconfigPathsPlugin({configFile: paths.appTsConfig})
new TsconfigPathsPlugin({ configFile: paths.appTsConfig }),
],
},
module: {
Expand Down Expand Up @@ -176,6 +190,7 @@ module.exports = {
// in development "style" loader enables hot editing of CSS.
{
test: /\.css$/,
exclude: /\.module\.css$/,
use: [
require.resolve('style-loader'),
{
Expand All @@ -186,30 +201,34 @@ module.exports = {
},
{
loader: require.resolve('postcss-loader'),
options: postCSSLoaderOptions,
},
],
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: /\.module\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
importLoaders: 1,
modules: true,
localIdentName: '[path]__[name]___[local]',
},
},
{
loader: require.resolve('postcss-loader'),
options: postCSSLoaderOptions,
},
],
},

// BIKO::START
{
test: /\.scss$/,
exclude: /\.module\.scss$/,
use: [
require.resolve('style-loader'),
{
Expand All @@ -220,24 +239,27 @@ module.exports = {
},
{
loader: require.resolve('postcss-loader'),
options: postCSSLoaderOptions,
},
require.resolve('sass-loader'),
],
},
{
test: /\.module\.scss$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
importLoaders: 1,
modules: true,
localIdentName: '[path]__[name]___[local]',
},
},
{
loader: require.resolve('postcss-loader'),
options: postCSSLoaderOptions,
},
require.resolve('sass-loader'),
],
},
Expand Down
121 changes: 90 additions & 31 deletions packages/react-scripts/config/webpack.config.prod.js
Expand Up @@ -55,6 +55,20 @@ const extractTextPluginOptions = shouldUseRelativeAssetPaths
{ publicPath: Array(cssFilename.split('/').length).join('../') }
: {};

// Options for PostCSS as we reference these options twice
// Adds vendor prefixing to support IE9 and above
const postCSSLoaderOptions = {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
flexbox: 'no-2009',
}),
],
};

// This is the production configuration.
// It compiles slowly and is focused on producing a fast and minimal bundle.
// The development configuration is different and lives in a separate file.
Expand Down Expand Up @@ -130,7 +144,7 @@ module.exports = {
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
new TsconfigPathsPlugin({configFile: paths.appTsConfig})
new TsconfigPathsPlugin({ configFile: paths.appTsConfig }),
],
},
module: {
Expand Down Expand Up @@ -186,8 +200,10 @@ module.exports = {
// tags. If you use code splitting, however, any async bundles will still
// use the "style" loader inside the async code so CSS from them won't be
// in the main CSS file.
// By default we support CSS Modules with the extension .module.css
{
test: /\.css$/,
exclude: /\.module\.css$/,
loader: ExtractTextPlugin.extract(
Object.assign(
{
Expand All @@ -208,24 +224,43 @@ module.exports = {
},
{
loader: require.resolve('postcss-loader'),
options: postCSSLoaderOptions,
},
],
},
extractTextPluginOptions
)
),
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: /\.module\.css$/,
loader: ExtractTextPlugin.extract(
Object.assign(
{
fallback: {
loader: require.resolve('style-loader'),
options: {
hmr: false,
},
},
use: [
{
loader: require.resolve('css-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
importLoaders: 1,
minimize: true,
sourceMap: shouldUseSourceMap,
modules: true,
localIdentName: '[path]__[name]___[local]',
},
},
{
loader: require.resolve('postcss-loader'),
options: postCSSLoaderOptions,
},
],
},
extractTextPluginOptions
Expand All @@ -237,6 +272,7 @@ module.exports = {
// BIKO::START
{
test: /\.scss$/,
exclude: /\.module\.scss$/,
loader: ExtractTextPlugin.extract(
Object.assign(
{
Expand All @@ -257,24 +293,47 @@ module.exports = {
},
{
loader: require.resolve('postcss-loader'),
options: postCSSLoaderOptions,
},
{
loader: require.resolve('sass-loader'),
options: {
sourceMap: shouldUseSourceMap,
},
},
],
},
extractTextPluginOptions
)
),
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
},
{
test: /\.module\.scss$/,
loader: ExtractTextPlugin.extract(
Object.assign(
{
fallback: {
loader: require.resolve('style-loader'),
options: {
hmr: false,
},
},
use: [
{
loader: require.resolve('css-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
importLoaders: 1,
minimize: true,
sourceMap: shouldUseSourceMap,
modules: true,
localIdentName: '[path]__[name]___[local]',
},
},
{
loader: require.resolve('postcss-loader'),
options: postCSSLoaderOptions,
},
{
loader: require.resolve('sass-loader'),
options: {
Expand Down
Expand Up @@ -21,6 +21,16 @@ describe('Integration', () => {
).to.match(/#feature-css-inclusion\{background:.+;color:.+}/);
});

it('css modules inclusion', async () => {
const doc = await initDOM('css-modules-inclusion');

expect(
doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '')
).to.match(
/.+__style-module___cssModulesInclusion+\{background:.+;color:.+}/
);
});

it('image inclusion', async () => {
const doc = await initDOM('image-inclusion');

Expand Down

0 comments on commit e87e139

Please sign in to comment.