Skip to content

Commit 2311570

Browse files
committed
Merge branch 'next' of https://github.com/facebook/create-react-app into sass-loader
2 parents 7ba882e + 14f4485 commit 2311570

File tree

10 files changed

+109
-16
lines changed

10 files changed

+109
-16
lines changed

packages/react-dev-utils/README.md

+37
Original file line numberDiff line numberDiff line change
@@ -326,3 +326,40 @@ module.exports = {
326326
// ...
327327
}
328328
```
329+
330+
#### `getCSSModuleLocalIdent(context: Object, localIdentName: String, localName: String, options: Object): string`
331+
332+
Creates a class name for CSS Modules that uses either the filename or folder name if named `index.module.css`.
333+
334+
For `MyFolder/MyComponent.module.css` and class `MyClass` the output will be `MyComponent.module_MyClass__[hash]`
335+
For `MyFolder/index.module.css` and class `MyClass` the output will be `MyFolder_MyClass__[hash]`
336+
337+
```js
338+
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
339+
340+
// In your webpack config:
341+
// ...
342+
module: {
343+
rules: [
344+
{
345+
test: /\.module\.css$/,
346+
use: [
347+
require.resolve('style-loader'),
348+
{
349+
loader: require.resolve('css-loader'),
350+
options: {
351+
importLoaders: 1,
352+
modules: true,
353+
getLocalIdent: getCSSModuleLocalIdent,
354+
},
355+
},
356+
{
357+
loader: require.resolve('postcss-loader'),
358+
options: postCSSLoaderOptions,
359+
},
360+
],
361+
}
362+
]
363+
}
364+
```
365+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
'use strict';
9+
10+
const loaderUtils = require('loader-utils');
11+
12+
module.exports = function getLocalIdent(
13+
context,
14+
localIdentName,
15+
localName,
16+
options
17+
) {
18+
// Use the filename or folder name, based on some uses the index.js / index.module.css project style
19+
const fileNameOrFolder = context.resourcePath.endsWith('index.module.css')
20+
? '[folder]'
21+
: '[name]';
22+
// Create a hash based on a the file location and class name. Will be unique across a project, and close to globally unique.
23+
const hash = loaderUtils.getHashDigest(
24+
context.resourcePath + localName,
25+
'md5',
26+
'base64',
27+
5
28+
);
29+
// Use loaderUtils to find the file or folder name
30+
const className = loaderUtils.interpolateName(
31+
context,
32+
fileNameOrFolder + '_' + localName + '__' + hash,
33+
options
34+
);
35+
// remove the .module that appears in every classname when based on the file.
36+
return className.replace('.module_', '_');
37+
};

packages/react-dev-utils/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"eslintFormatter.js",
2020
"FileSizeReporter.js",
2121
"formatWebpackMessages.js",
22+
"getCSSModuleLocalIdent.js",
2223
"getProcessForPort.js",
2324
"ignoredFiles.js",
2425
"inquirer.js",

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
1717
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
1818
const eslintFormatter = require('react-dev-utils/eslintFormatter');
1919
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
20+
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
2021
const getClientEnvironment = require('./env');
2122
const paths = require('./paths');
2223

@@ -284,7 +285,7 @@ module.exports = {
284285
{
285286
importLoaders: 1,
286287
modules: true,
287-
localIdentName: CSSModulePattern,
288+
getLocalIdent: getCSSModuleLocalIdent,
288289
},
289290
'postcss-loader',
290291
postCSSLoaderOptions

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
1919
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
2020
const eslintFormatter = require('react-dev-utils/eslintFormatter');
2121
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
22+
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
2223
const paths = require('./paths');
2324
const getClientEnvironment = require('./env');
2425

@@ -313,7 +314,7 @@ module.exports = {
313314
minimize: true,
314315
sourceMap: shouldUseSourceMap,
315316
modules: true,
316-
localIdentName: CSSModulePattern,
317+
getLocalIdent: getCSSModuleLocalIdent,
317318
},
318319
'postcss-loader',
319320
postCSSLoaderOptions

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ describe('Integration', () => {
2626

2727
expect(
2828
doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '')
29+
).to.match(/.+style_cssModulesInclusion__.+\{background:.+;color:.+}/);
30+
expect(
31+
doc.getElementsByTagName('style')[1].textContent.replace(/\s/g, '')
2932
).to.match(
30-
/.+__style-module___cssModulesInclusion+\{background:.+;color:.+}/
33+
/.+assets_cssModulesIndexInclusion__.+\{background:.+;color:.+}/
3134
);
3235
});
3336

packages/react-scripts/fixtures/kitchensink/src/features/webpack/CssModulesInclusion.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77

88
import React from 'react';
99
import styles from './assets/style.module.css';
10+
import indexStyles from './assets/index.module.css';
1011

1112
export default () => (
12-
<p className={styles.cssModulesInclusion}>CSS Modules are working!</p>
13+
<div>
14+
<p className={styles.cssModulesInclusion}>CSS Modules are working!</p>
15+
<p className={indexStyles.cssModulesInclusion}>
16+
CSS Modules with index are working!
17+
</p>
18+
</div>
1319
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.cssModulesIndexInclusion {
2+
background: darkblue;
3+
color: lightblue;
4+
}

packages/react-scripts/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"html-webpack-plugin": "2.30.1",
5151
"identity-obj-proxy": "3.0.0",
5252
"jest": "22.1.2",
53+
"loader-utils": "^1.1.0",
5354
"object-assign": "4.1.1",
5455
"postcss-flexbugs-fixes": "3.2.0",
5556
"postcss-loader": "2.0.10",

packages/react-scripts/template/README.md

+14-12
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ class Button extends Component {
509509
}
510510
```
511511

512-
**This is not required for React** but many people find this feature convenient. You can read about the benefits of this approach [here](https://medium.com/seek-ui-engineering/block-element-modifying-your-javascript-components-d7f99fcab52b). However you should be aware that this makes your code less portable to other build tools and environments than Webpack.
512+
**This is not required for React** but many people find this feature convenient. You can read about the benefits of this approach [here](https://medium.com/seek-blog/block-element-modifying-your-javascript-components-d7f99fcab52b). However you should be aware that this makes your code less portable to other build tools and environments than Webpack.
513513

514514
In development, expressing dependencies this way allows your styles to be reloaded on the fly as you edit them. In production, all CSS files will be concatenated into a single minified `.css` file in the build output.
515515

@@ -518,49 +518,51 @@ If you are concerned about using Webpack-specific semantics, you can put all you
518518
<!---
519519
## Adding a CSS Modules stylesheet
520520
521-
This project supports [CSS Modules](https://github.com/css-modules/css-modules) alongside regular stylesheets using the **[name].module.css** file naming convention. CSS Modules allows the scoping of CSS by automatically creating a unique classname of the format **[dir]\_\_[filename]___[classname]**.
521+
This project supports [CSS Modules](https://github.com/css-modules/css-modules) alongside regular stylesheets using the **[name].module.css** file naming convention. CSS Modules allows the scoping of CSS by automatically creating a unique classname of the format **[filename]\_[classname]\_\_[hash]**.
522522
523523
An advantage of this is the ability to repeat the same classname within many CSS files without worrying about a clash.
524524
525525
### `Button.module.css`
526526
527527
```css
528-
.button {
529-
padding: 20px;
528+
.error {
529+
background-color: red;
530530
}
531531
```
532532
533533
### `another-stylesheet.css`
534534
535535
```css
536-
.button {
537-
color: green;
536+
.error {
537+
color: red;
538538
}
539539
```
540540
541541
### `Button.js`
542542
543543
```js
544544
import React, { Component } from 'react';
545-
import './another-stylesheet.css'; // Import regular stylesheet
546545
import styles from './Button.module.css'; // Import css modules stylesheet as styles
546+
import './another-stylesheet.css'; // Import regular stylesheet
547+
547548
548549
class Button extends Component {
549550
render() {
550-
// You can use them as regular CSS styles
551-
return <div className={styles.button} />;
551+
// reference as a js object
552+
return <button className={styles.error}>Error Button</button>;
552553
}
553554
}
554555
```
555556
### `exported HTML`
556-
No clashes from other `.button` classnames
557+
No clashes from other `.error` class names
557558
558559
```html
559-
<div class="src__Button-module___button"></div>
560+
<!-- This button has red background but not red text -->
561+
<button class="Button_error_ax7yz"></div>
560562
```
561563
562564
**This is an optional feature.** Regular html stylesheets and js imported stylesheets are fully supported. CSS Modules are only added when explictly named as a css module stylesheet using the extension `.module.css`.
563-
--->
565+
-->
564566
565567
## Post-Processing CSS
566568

0 commit comments

Comments
 (0)