Umi offers a lot of functionality out of the box, and one that I find really useful is support for automatic use of CSS Modules. This article will share how to use this feature in create-React-app and explain how it works.
What is automatically using CSS Modules
Those of you who have used Umi or Ant Design Pro should know that you can use CSS Modules in a project by writing import
// Use CSS Modules
import styles from './index.less';
/ / no use
import './index.less';
Copy the code
This is a very convenient way to write it. However, this functionality is not native to CSS-Loader because loader does not know how the file is referenced. Therefore, in create-react-app, you need to identify the use of CSS Modules by adding.module to the style file name. Such as:
// Use CSS Modules
import styles from './index.module.less';
/ / no use
import styles from './index.less';
import './index.less';
Copy the code
This method has strong constraints on file names, so Umi has optimized this situation.
How to use
The first step is to make create-React-app webpack configurable with craco.
Craco functions like React-app-Rewired, but is friendlier than its configuration. Craco extracts common configurations as configuration items, while React-app-Rewired can only modify webpack configurations through transformation functions, and customize-cra is often used together.
Install Craco and the plugin craco-CSS-Modules
$ npm install @craco/craco craco-css-modules -D
Copy the code
Create the build folder and create the craco.config.js file with the following contents:
const CracoCSSModules = require('craco-css-modules');
module.exports = {
plugins: [{plugin: CracoCSSModules },
]
};
Copy the code
Modify NPM scripts in package.json
"scripts": {-"start": "react-scripts start",
+ "start": "craco start",
- "build": "react-scripts build",
+ "build": "craco build"
}
Copy the code
Add a cracoConfig field to package.json and point to the configuration file
"cracoConfig": "./build/craco.config.js"
Copy the code
You can also choose to create craco.config.js or.cracorc.js in the project root directory using the craco-supported convention. Personally, I don’t like having a lot of files in the root directory.
That’s it. You don’t need the special.module.css.
Verified in the following versions:
- react-scripts:
^ 5.0.0
- @craco/craco:
^ 6.4.0
- craco-css-modules:
^ 1.0.1
Less support
Create-react-app does not support less. You can use craco-less.
Install the plug-in Craco-less
$ npm install craco-less -D
Copy the code
Use the plugin in craco.config.js:
const CracoLess = require('craco-less');
const CracoCSSModules = require('craco-css-modules');
module.exports = {
plugins: [{plugin: CracoLess },
{ plugin: CracoCSSModules },
],
};
Copy the code
Use the less syntax
Verified in the following versions:
- craco-less:
^ 2.0.0
The principle of
Create-react-app generates the following parsing configuration for CSS files (similar to less and sass) by printing the Webpack configuration:
modules: {
rules: [{test: /\.css$/,
use: [
{
loader: 'css-loader'.modules: false,},],}, {test: /\.module\.css$/,
use: [
{
loader: 'css-loader'.modules: {
localIdentName: ' ',},},],}Copy the code
Therefore, create-react-app determines whether modules are enabled by csS-loader by determining the.module in the file name. How about not passing the file name? We can use resourceQuery to add query parameters to files that need to be opened.
modules: {
rules: [{test: /\.css$/,
oneOf: [
{
resourceQuery: /modules/,
use: [
{
loader: 'css-loader'.modules: {
localIdentName: ' ',},},],}, {use: [{loader: 'css-loader'.modules: false,},],},],}Copy the code
How do I make these less files have this query? We can do this with Babel by modifying the AST (abstract syntax tree) to import… Concatenation of less files referenced in from syntax? The modules of the query.
const CSS_EXT_NAMES = ['.css'.'.less'.'.sass'.'.scss'];
function transform() {
return {
visitor: {
ImportDeclaration(path, { opts }) {
const {
specifiers,
source,
source: { value },
} = path.node;
if (specifiers.length && CSS_EXT_NAMES.includes(extname(value))) {
source.value = `${value}?${opts.flag || 'modules'}`; ,}}}}; }Copy the code
The above implementation comes from @umijs/ babel-plugin-auto-csS-modules. Craco-css-modules does not use Babel to support esbuild. But by Webpack plug-in AutoCSSModulesWebpackPlugin implementation. The principle is the same.
After the above conversion, less files that use CSS Modules will end with an extra query, which will be processed by Webpack using the CSS-loader that turns Modules on.
To summarize the principles, the key points are:
- Configure Webpack
modules.resolve
Through theoneOf
+resourceQuery
Enable CSS Modules for style files with Query - Through the Babel to
import
.from
The grammaticalless
File add query
Craco – CSS -modules is also based on the above principle, through the crACO plug-in mechanism to modify the configuration of Webpack. Source code: github.com/crazyurus/c…
The sample project
The following is a complete project using craco craco-less CRaco-CSS-modules, which supports automatic use of CSS modules. For your reference.
- Github.com/crazyurus/c…