foreword
css module
The advantage is that conflicts can be avoided namespace
, especially when the project is relatively large. import cls from 'XXX.css'
Today, when I wanted to use the import style in the react project I built myself css modules
, I found the following situation on the page↓, and I found out after printing it.cls = underfined
Reason:
css-loader
Theoptons.modules
default configuration isundefined
that it needs to match a specific regular to enablecss modules
The key issue
- Question : Normal activation
modules
will make the styles that you want to use as global lose their effect, because they are all converted into unique values. If you do not open them globally, you can only specify the suffix name to distinguish them.css modules
- The right way: let
webpack
automatic recognition be enabledcss modules
ideas
Final goal: open modules in css-loader according to rule matching
- To distinguish whether it is enabled or not
css modules
is to distinguishimport './index.css'
and to see what is the difference betweenimport cls from './index.css'
the corresponding conversion to AST css modules
Label the enabled files according to this different field- Use
webpack
therules
rule matching field oneOf to match
Refer to the implementation of umi css module
Source code: babel-plugin-auto-css-modules By writing a Babel
plug- in ,import
adding parameters to the , matching this parameter, and performing different configurations.url
webpack
babel plugin
// babel插件 --- css-modules.js
const { extname } = require("path");
const CSS_EXTNAMES = [".css", ".scss", ".sass", ".less"];
module.exports = () => {
return {
visitor: {
ImportDeclaration(path) {
const { specifiers, source } = path.node;
const { value } = source;
if (specifiers.length > 0 && CSS_EXTNAMES.includes(extname(value))) {
source.value = `${value}?css_modules`; // 在路径末尾加上 css_modules 用于 webpack 匹配该文件,如 import Test from './test.less'; 变成 import Test from './test.less?css_modules';
}
},
},
};
};
复制代码
.babelrc
Introduce plugins in
{
"presets": [
"@babel/env",
[
"@babel/preset-react",
{"runtime": "automatic"}
],
],
"plugins": ["./css-modules"]
}
复制代码
Test whether the plugin is effectively imported
if (
specifiers.length > 0 &&
CSS_FILE_EXTENSIONS.includes(extname(value))
) {
console.log(value); // 启动webpack 有看到打印值就可以了
source.value = `${value}?css_modules`;
}
复制代码
configured webpack
_rules
const rules = [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /(node_modules|bower_components)/,
use: 'babel-loader',
},
{
test: /\.css$/,
oneOf: [
{
resourceQuery: /css_modules/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader', options: { modules: true } },
// { loader: 'less-loader' }, less加上即可
],
},
{
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
//{ loader: 'less-loader' },
],
},
],
},
];
复制代码
Use the ability of resourceQuery to query whether there are specific parameters to determine whether to enable
css-module
the function. Achieving the form without modifying the file name, compatible with commoncss
andcss-module
style files, simple and elegant :)
final effect
CSS modules can be used normally without special suffix names, and global styles are also inserted into the DOM normally, prefect.