Skip to content

Commit 91b16c6

Browse files
committed
Merge branch 'add-css-modules' of https://github.com/ro-savage/create-react-app into ro-savage-add-css-modules
2 parents a51be95 + 6d9dffb commit 91b16c6

File tree

11 files changed

+196
-32
lines changed

11 files changed

+196
-32
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ Some features are currently **not supported**:
191191

192192
* Server rendering.
193193
* Some experimental syntax extensions (e.g. decorators).
194-
* CSS Modules.
195194
* Importing LESS or Sass directly ([but you still can use them](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-css-preprocessor-sass-less-etc)).
196195
* Hot reloading of components.
197196

packages/react-scripts/config/webpack.config.dev.js

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@ const publicUrl = '';
3232
// Get environment variables to inject into our app.
3333
const env = getClientEnvironment(publicUrl);
3434

35+
// Options for PostCSS as we reference these options twice
36+
// Adds vendor prefixing to support IE9 and above
37+
const postCSSLoaderOptions = {
38+
// Necessary for external CSS imports to work
39+
// https://github.com/facebookincubator/create-react-app/issues/2677
40+
ident: 'postcss',
41+
plugins: () => [
42+
require('postcss-flexbugs-fixes'),
43+
autoprefixer({
44+
browsers: [
45+
'>1%',
46+
'last 4 versions',
47+
'Firefox ESR',
48+
'not ie < 9', // React doesn't support IE8 anyway
49+
],
50+
flexbox: 'no-2009',
51+
}),
52+
],
53+
};
54+
3555
// This is the development configuration.
3656
// It is focused on developer experience and fast rebuilds.
3757
// The production configuration is different and lives in a separate file.
@@ -185,8 +205,10 @@ module.exports = {
185205
// "style" loader turns CSS into JS modules that inject <style> tags.
186206
// In production, we use a plugin to extract that CSS to a file, but
187207
// in development "style" loader enables hot editing of CSS.
208+
// By default we support CSS Modules with the extension .module.css
188209
{
189210
test: /\.css$/,
211+
exclude: /\.module\.css$/,
190212
use: [
191213
require.resolve('style-loader'),
192214
{
@@ -197,24 +219,28 @@ module.exports = {
197219
},
198220
{
199221
loader: require.resolve('postcss-loader'),
222+
options: postCSSLoaderOptions,
223+
},
224+
],
225+
},
226+
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
227+
// using the extension .module.css
228+
{
229+
test: /\.module\.css$/,
230+
use: [
231+
require.resolve('style-loader'),
232+
{
233+
loader: require.resolve('css-loader'),
200234
options: {
201-
// Necessary for external CSS imports to work
202-
// https://github.com/facebookincubator/create-react-app/issues/2677
203-
ident: 'postcss',
204-
plugins: () => [
205-
require('postcss-flexbugs-fixes'),
206-
autoprefixer({
207-
browsers: [
208-
'>1%',
209-
'last 4 versions',
210-
'Firefox ESR',
211-
'not ie < 9', // React doesn't support IE8 anyway
212-
],
213-
flexbox: 'no-2009',
214-
}),
215-
],
235+
importLoaders: 1,
236+
modules: true,
237+
localIdentName: '[name]__[local]___[hash:base64:5]',
216238
},
217239
},
240+
{
241+
loader: require.resolve('postcss-loader'),
242+
options: postCSSLoaderOptions,
243+
},
218244
],
219245
},
220246
// "file" loader makes sure those assets get served by WebpackDevServer.

packages/react-scripts/config/webpack.config.prod.js

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,26 @@ const extractTextPluginOptions = shouldUseRelativeAssetPaths
5656
{ publicPath: Array(cssFilename.split('/').length).join('../') }
5757
: {};
5858

59+
// Options for PostCSS as we reference these options twice
60+
// Adds vendor prefixing to support IE9 and above
61+
const postCSSLoaderOptions = {
62+
// Necessary for external CSS imports to work
63+
// https://github.com/facebookincubator/create-react-app/issues/2677
64+
ident: 'postcss',
65+
plugins: () => [
66+
require('postcss-flexbugs-fixes'),
67+
autoprefixer({
68+
browsers: [
69+
'>1%',
70+
'last 4 versions',
71+
'Firefox ESR',
72+
'not ie < 9', // React doesn't support IE8 anyway
73+
],
74+
flexbox: 'no-2009',
75+
}),
76+
],
77+
};
78+
5979
// This is the production configuration.
6080
// It compiles slowly and is focused on producing a fast and minimal bundle.
6181
// The development configuration is different and lives in a separate file.
@@ -194,8 +214,10 @@ module.exports = {
194214
// tags. If you use code splitting, however, any async bundles will still
195215
// use the "style" loader inside the async code so CSS from them won't be
196216
// in the main CSS file.
217+
// By default we support CSS Modules with the extension .module.css
197218
{
198219
test: /\.css$/,
220+
exclude: /\.module\.css$/,
199221
loader: ExtractTextPlugin.extract(
200222
Object.assign(
201223
{
@@ -211,24 +233,38 @@ module.exports = {
211233
},
212234
{
213235
loader: require.resolve('postcss-loader'),
236+
options: postCSSLoaderOptions,
237+
},
238+
],
239+
},
240+
extractTextPluginOptions
241+
)
242+
),
243+
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
244+
},
245+
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
246+
// using the extension .module.css
247+
{
248+
test: /\.module\.css$/,
249+
loader: ExtractTextPlugin.extract(
250+
Object.assign(
251+
{
252+
fallback: require.resolve('style-loader'),
253+
use: [
254+
{
255+
loader: require.resolve('css-loader'),
214256
options: {
215-
// Necessary for external CSS imports to work
216-
// https://github.com/facebookincubator/create-react-app/issues/2677
217-
ident: 'postcss',
218-
plugins: () => [
219-
require('postcss-flexbugs-fixes'),
220-
autoprefixer({
221-
browsers: [
222-
'>1%',
223-
'last 4 versions',
224-
'Firefox ESR',
225-
'not ie < 9', // React doesn't support IE8 anyway
226-
],
227-
flexbox: 'no-2009',
228-
}),
229-
],
257+
importLoaders: 1,
258+
minimize: true,
259+
sourceMap: true,
260+
modules: true,
261+
localIdentName: '[name]__[local]___[hash:base64:5]',
230262
},
231263
},
264+
{
265+
loader: require.resolve('postcss-loader'),
266+
options: postCSSLoaderOptions,
267+
},
232268
],
233269
},
234270
extractTextPluginOptions

packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ describe('Integration', () => {
2323
).to.match(/#feature-css-inclusion\{background:.+;color:.+}/);
2424
});
2525

26+
it('css modules inclusion', async () => {
27+
const doc = await initDOM('css-modules-inclusion');
28+
29+
expect(
30+
doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '')
31+
).to.match(
32+
/\.style-module__cssModulesInclusion___.+\{background:.+;color:.+}/
33+
);
34+
});
35+
2636
it('image inclusion', async () => {
2737
const doc = await initDOM('image-inclusion');
2838

packages/react-scripts/fixtures/kitchensink/src/App.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ class App extends Component {
8383
this.setFeature(f.default)
8484
);
8585
break;
86+
case 'css-modules-inclusion':
87+
import(
88+
'./features/webpack/CssModulesInclusion'
89+
).then(f => this.setFeature(f.default));
90+
break;
8691
case 'custom-interpolation':
8792
import('./features/syntax/CustomInterpolation').then(f =>
8893
this.setFeature(f.default)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
import React from 'react';
11+
import styles from './assets/style.module.css';
12+
13+
export default () => (
14+
<p className={styles.cssModulesInclusion}>CSS Modules are working!</p>
15+
);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
import React from 'react';
11+
import ReactDOM from 'react-dom';
12+
import CssModulesInclusion from './CssModulesInclusion';
13+
14+
describe('css modules inclusion', () => {
15+
it('renders without crashing', () => {
16+
const div = document.createElement('div');
17+
ReactDOM.render(<CssModulesInclusion />, div);
18+
});
19+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.cssModulesInclusion {
2+
background: darkblue;
3+
color: lightblue;
4+
}

packages/react-scripts/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"file-loader": "0.11.2",
4444
"fs-extra": "3.0.1",
4545
"html-webpack-plugin": "2.29.0",
46+
"identity-obj-proxy": "^3.0.0",
4647
"jest": "20.0.4",
4748
"object-assign": "4.1.1",
4849
"postcss-flexbugs-fixes": "3.2.0",

packages/react-scripts/scripts/utils/createJestConfig.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,13 @@ module.exports = (resolve, rootDir, isEjecting) => {
3939
'^.+\\.css$': resolve('config/jest/cssTransform.js'),
4040
'^(?!.*\\.(js|jsx|css|json)$)': resolve('config/jest/fileTransform.js'),
4141
},
42-
transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'],
42+
transformIgnorePatterns: [
43+
'[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$',
44+
'^.+\\.module\\.css$',
45+
],
4346
moduleNameMapper: {
4447
'^react-native$': 'react-native-web',
48+
'^.+\\.module\\.css$': 'identity-obj-proxy',
4549
},
4650
moduleFileExtensions: ['web.js', 'js', 'json', 'web.jsx', 'jsx', 'node'],
4751
};

0 commit comments

Comments
 (0)