preface
Every time you debug the code, you will see the class style after the CSS Module processes it. Before, I always thought that the hash value was related to the style in the class or the DOM node referencing the class. After trying to modify the style in the class and the DOM where the class resides, I found that the class name did not change. Curious about CSS Module type generation rules.
data
This article considers that class names should be hashed. If class names are hashed, two identical class names must produce the same hash, which does not solve the problem of class name conflicts. I searched some information on The CSS Module hash generation rules on Google, but did not solve the doubts.
The source code
The CSS Module is enabled in csS-Loader of webPack, and the configuration information of CSS-Loader is displayed
config.module
.rule('css')
.test(/.css$/)
.set('sideEffects', true)
.when(options.cssModules, function (rule) {
rule.oneOf('module')
.resourceQuery(/module/)
.use('style')
.loader(r('style-loader'))
.end()
.use('css')
.loader(r('css-loader'))
.options(__assign(__assign({}, cssOptions), { importLoaders: 1 }))
.end()
.use('postcss')
.loader(r('postcss-loader'))
.options({ sourceMap: sourceMap, postcssOptions: postcssOptions })
.end()
.end();
})
var cssOptions = __assign(__assign({}, cssOptionsNormal), { modules: {
localIdentName: '[name]_[local]_[hash:base64:5]',
localIdentContext: srcContext
} });
var srcContext = path_1.default.join(context, 'src');
Copy the code
[name] [local] [hash:base64:5]. This configuration can explain why the base64 hash has five bits.
Not much valid information was found in the WebPack configuration.
Have to go to csS-Loader source code to explore.
The hash generation rule is located by debugging to the defaultGetLocalIdent function in the SRC /utils.js file.
(There is an episode here, webpack uses csS-Loader version 5.2.0, download source code is the MASTER branch of CSS-Loader, there is a big difference, later switch source code to 5.2.0debug code is more consistent with the source code structure, there is a mistake.)
function defaultGetLocalIdent(
loaderContext,
localIdentName,
localName,
options
) {
let relativeMatchResource = "";
// eslint-disable-next-line no-underscore-dangle
if (loaderContext._module && loaderContext._module.matchResource) {
relativeMatchResource = `${normalizePath(
// eslint-disable-next-line no-underscore-dangle
path.relative(options.context, loaderContext._module.matchResource)
)}\x00`;
}
const relativeResourcePath = normalizePath(
path.relative(options.context, loaderContext.resourcePath)
);
// eslint-disable-next-line no-param-reassign
options.content = `${options.hashPrefix}${relativeMatchResource}${relativeResourcePath}\x00${localName}`;
return interpolateName(loaderContext, localIdentName, options);
}
Copy the code
InterpolateName finally returns the result after the interpolateName function is executed. This function is located in the lib/interpolateName. Js file in the loader-utils library. The following is a code in function interpolateName(loaderContext, name, options) which is also the core algorithm for generating the HASH of CSS Module class names
if (content) { // Match hash template url = url // `hash` and `contenthash` are same in `loader-utils` context // let's keep `hash` for backward compatibility .replace( /[(?:([^:]]+):)? (? :hash|contenthash)(? ::([a-z]+\d*))? (? ::(\d+))? ] /gi, (all, hashType, digestType, maxLength) => getHashDigest(content, hashType, digestType, parseInt(maxLength, 10)) ) .replace(/[emoji(?::(\d+))?] /gi, (all, length) => encodeStringToEmoji(content, parseInt(length, 10)) ); }Copy the code
You can see that the following function is called to get the hash value
getHashDigest(content, hashType, digestType, parseInt(maxLength, 10))
Copy the code
Debug to see what is passed as an input parameter,
The content of the input parameter consists of the path to the vue file and the class name, encrypted base64, which explains why changing the style in the class or changing the DOM ultimately generates the class name unchanged.
conclusion
From the above source code analysis, it is concluded that the HASH in the CSS Module class name is composed of path and class name
validation
In the comment – the title, for example
.comment-title {
height: 26px;
font-size: 18px;
font-weight: 500;
color: #111111;
line-height: 26px;
margin-left: 16px;
margin-right: 16px;
}
Copy the code
The vue file to which it is applied is named
The compiled class name of this class is
Now we modify the vue file name that references this class
The final compiled class name is changed to
The class name has changed, which also confirms the above conclusion