差不多疯了,严重高估我自己,本以为周六一天能搞定UI,结果装了个React18之后,发现好多东西都不一样了,记录一下。 这篇是怎么配less的。
一些版本:
{
"dependencies": {
"react": "^18.2.0",
"webpack": "^5.64.4",
"typescript": "^4.9.5",
},
"devDependencies": {
"less": "^4.2.0",
"less-loader": "^11.1.3"
}
}
首先 npm run eject 暴露配置。
在 config/webpack.config.js 里改:
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/; // to support less
const lessModuleRegex = /\.module\.less$/; // to support module.less
找sassRegex 和 sassModuleRegex 在哪里,copy,然后改成less
{
test: lessRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'icss',
},
},
'less-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
// sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'local',
getLocalIdent: getCSSModuleLocalIdent,
},
},
'less-loader'
),
},
这个时候,应该已经能support 这种语法了
import 'xx.less'; import 'xx.module.less'
但是通常我们还想做到像vue的<style lang="less" scoped>的效果,所以我们还需要让ts认识xx.module.less。找到react-app-env.d.ts,模仿'*.module.sass' 写一个for less。
declare module '*.module.less' {
const classes: {[key:string]: string};
export default classes;
}
搞定,不会报错了。
如果在browser里面你的className={${styles.myLessStyle}} 编译出来是 undefined,请继续改webpack.config.js 吧。先找到这一段
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'local',
getLocalIdent: getCSSModuleLocalIdent,
},
},
'less-loader'
),
},
getLocalIdent 就是用来定义你编译出来的class名字。它在这里const getCSSModuleLocalIdent = require("react-dev-utils/getCSSModuleLocalIdent");。跟进源代码看看,发现它并不支持less。如果你的项目不用重新npm install,直接改掉就行。如果你跟我一样,因为用jekins build package 的时候规定必须重新npm install,那就把"react-dev-utils/getCSSModuleLocalIdent"copy 到webpack.config.js,改它
const getLessModuleLocalIdent = (
context,
localIdentName,
localName,
options
) => {
// Use the filename or folder name, based on some uses the index.js / index.module.(css|scss|sass) project style
const fileNameOrFolder = context.resourcePath.match(
/index\.module\.(css|scss|sass|less)$/
)
? '[folder]'
: '[name]';
// Create a hash based on a the file location and class name. Will be unique across a project, and close to globally unique.
const hash = loaderUtils.getHashDigest(
path.posix.relative(context.rootContext, context.resourcePath) + localName,
'md5',
'base64',
5
);
// Use loaderUtils to find the file or folder name
const className = loaderUtils.interpolateName(
context,
fileNameOrFolder + '_' + localName + '__' + hash,
options
);
// Remove the .module that appears in every classname when based on the file and replace all "." with "_".
return className.replace('.module_', '_').replace(/\./g, '_');
};
然后test: lessModuleRegex的 getLocalIdent改成getLessModuleLocalIdent。好,Fixed liao leh!
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'local',
getLocalIdent: getLessModuleLocalIdent,
},
},
'less-loader'
),
},
再试试
import styles from 'xx.module.less';
const myComponent = () => {
return <div className={`${styles.myLessStyle}`}></div>
}
export default myComponent
这个div的class 应该会被翻译成 xx_myLessStyle_一串哈希码