React中使用less(use CSS Modules)的两种配置方法

创建日期: 2020年3月2日
Demo源码下载
参考链接:
链接1
链接2
customize-cra API

前言:
如果你想通过不暴露webpack,配置less,并且只想知道步骤,不关心你配置时候为什么不好用,可以直接划到下面看【3.总结】。
如果,你是初学者小白,并没有项目,你需要做如下准备工作:
用create-react-app (CRA)脚手架或者IDE创建React项目。
参考:React入门(1)——我的第一个React.js项目

1.安装less和less-loader

//npm 
$ npm install --save-dev less-loader less
//yarn
$ yarn add less less-loader -D

遗留问题:为什么我按官网的命令去安装less,在package.json里面不会显示,而用上面的方式,就会显示呢?需要查下npm的子命令了。[参考]

安装后,我们会看到package.json文件中,添加了依赖:

  "devDependencies": {
    "less": "^3.11.1",
    "less-loader": "^5.0.0"
  }

Dependencies和devDependencies到底有什么区别呢?[参考链接]

2. 配置

2.1 方法一:暴露webpack

哇啊!好尴尬,翻了半天,也没找到网上说的webpack.config.js文件,原因看这个。

下面这个命令,谨慎执行,因为不可逆。但是只要做好代码版本管理,可以随意折腾,大不了重头再来版本管理git的使用

2.1.1 yarn eject

$ yarn eject

执行的时候,有提示:NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018/10/01/create-react-app-v2.html
因为,执行该命令后会把已构建依赖项、配置文件和脚本复制到程序目录中。该操作是不可逆转的,执行完成后会删除这个命令,也就是说只能执行一次。

插曲:执行的时候,被git给阻挡了,因为是在学习,所以我直接用

$ find . -name ".git" | xargs rm -Rf

用这个命令把git给清除了。如果是项目,自己按照提示,把git相关的commit,stash什么的,处理完毕就好。
执行完毕后,package.json文件被更改了,与此同时,会生成新文件夹config:


React中使用less(use CSS Modules)的两种配置方法_第1张图片
config文件夹

2.1.2修改webpack.config.js配置文件。

我们找到sassRegex,模仿它来配置lessRegex。
(1).配置less

// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/; //这一句和下一句是新增的less的配置
const lessModuleRegex = /\.module\.less$/;

(2).配置less-loader
找到"test: sassRegex"这个,搜一下即可,然后模仿这个来写less的。

// Adds support for CSS Modules, but using LESS
            {
              test: lessRegex,
              exclude: lessModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  modules: true,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'less-loader'
              ),
              sideEffects: true,
            },
            {
              test: lessModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                  modules: {
                    getLocalIdent: getCSSModuleLocalIdent,
                  },
                },
                'less-loader'
              ),
            },

这里,我先直接copy了sass的配置,然后改成less,运行后不好用。之后,又在lessRegex里加了一句modules: true,才可以运行。致于 importLoaders: 3,这后面的数字,是3,是1,都好用,没有查具体意义。待调查

2.1.3 修改代码

新建styles.less文件:

//styles.less
.title {
  color: red;
}

修改index.js文件:

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import styles from './styles.less'

const App = () => {
  console.log(styles);//打印一下,是一个对象,对象的元素的key是title
  return(
    

Hello world

) } ReactDOM.render(, document.getElementById('root'));

这里,引入less文件,作为styles,设置className的时候,将原本的双引号,改成花括号。至此,less的引用成功。

参考链接1:样式设置和CSS文件引入
配置的时候请注意:关于 less 配置规则放在 sass 的解析规则下面即可,如果放在了 file-loader 的解析规则下面,less 文件解析不会生效。(这段注意来自于网络,没有验证过)



2.2 配置方法二:无需eject进行配置(不用暴露webpack)

参考1: Create React App无eject配置(react-app-rewired 和 customize-cra)
参考2: create-react-app 优雅定制指南

初学者:因为,eject是一个不可逆的过程,所以,这里,你需要重新创建一个项目来实验。新建项目后,参照上面,修改代码,新建styles.less文件,以及修改inde.js文件。记得要安装less和less-loader。然后,运行。嗯,hello world是黑色的,styles.less的文件没有被成功调用。

下面,我们来进行第二种,相对优雅的设置方案。
react-app-rewired
是 react 社区开源的一个修改 CRA 配置的工具。纯 react-app-rewired 的方式自定义配置,参考 Extended Configuration Options 文档。
注意
react-app-rewired 1.x 配合 create-react-app 1.x
react-app-rewired 2.x 配合 create-react-app 2.x

版本升级导致互不兼容,另外,react-app-rewired 2.x 应该是社区维护了。
react-app-rewired@^2.0.0+ 版本需要搭配 customize-cra 使用

在 react-app-rewired 1.x 的版本中,它除了提供覆盖配置的方法,还体用了一些 helpers,例如 rewireLess、rewirePreact 等,2.x 版本只保留了核心功能。
另外一个工具帮我们实现了这些,customize-cra.

customize-cra
这次我们使用 customize-cra 协助自定义,参考 Using the plugins 文档。

2.2.1 安装

yarn add react-app-rewired customize-cra -D

2.2.2 修改package.json文件

//package.json
"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test --env=jsdom",
    "eject": "react-scripts eject"
  },

2.2.3 在项目根目录新建config-overrides.js

//config-overrides.js
const { override } = require('customize-cra');
module.exports = {};

2.2.4 配置less (在react使用JavaScript语言下)

在第一部分中,我们已经安装了less和less-loader依赖,这里我们开始配置。
这个过程中,笔者找了很多文章来看,大部分都是依赖react-app-rewired来做的,但是,文章比较老,现在版本更新,我们需要[customize-cra]来协助。
customize-cra API docs
addLessLoader(loaderOptions)
我们来修改config-overrides.js文件:

//config-overrides.js
const { override, addLessLoader } = require('customize-cra');

module.exports = override(
  
  addLessLoader({
    strictMath: true,
    noIeCompat: true,
    localIdentName: "[local]--[hash:base64:5]" // if you use CSS Modules, and custom `localIdentName`, default is '[local]--[hash:base64:5]'.
  }),
)

好了,less配置成功,来运行你的代码吧!
,什么???不好用???
没错,确实不好用!笔者也在这里卡住了,读了数十篇文章,依然没有找到解决方案,最终,还是回归官网的文档,才搞明白缘由。
其实,CRA生成的React项目,是可以直接用css modules的,但是,css文件的命名是有规则的,例如:styles.module.css。同理依赖css modules的less,文件名的命名规则也如此:styles.module.less。
好了,我们修改下文件名及index.js里的引用,再运行一次代码。
报错:


React中使用less(use CSS Modules)的两种配置方法_第2张图片
image.png

至此,我已哭死!!!调查后,发现是因为css-loader更新到3.0以后,出现的这个问题,也因此,之前博客的方法,都不起作用。

参考1: https://github.com/arackaf/customize-cra/issues/201
我们先将"customize-cra": "^1.0.0-alpha.0"升级,此时,用的就是这个版本的,
然后参考:https://github.com/rails/webpacker/issues/2197的gyurcigyurma说的,将config-overrides.js文件改成如下:(此时,使用的是styles.module.less文件名)

//config-overrides.js
const { override, addLessLoader } = require('customize-cra');

module.exports = override(
  addLessLoader({
    strictMath: true,
    noIeCompat: true,
    loader: "css-loader",
    options: {
      modules: {
        localIdentName: "[name]__[local]___[hash:base64:5]",
      },
      sourceMap: true
    }
  }),
)

好了,我看到红色的Hello world了,终于可以正确运行了。。。

2.2.5 配置less(在react使用TypeScript语言下)

用IDE新建项目,比如webStorm,新建时,选择支持TypeScript。参考上面的1~4,进行一次,less文件用styles.modules.less这种.modules.less命名规则。我们也要更新customize-cra的版本。
除此之外,还有修改react-app-env.d.ts文件:

//react-app-env.d.ts
declare module "*.module.less"

笔者第二次执行时,运行一直出错,提示:

./src/styles.module.less (./node_modules/css-loader/dist/cjs.js??ref--6-oneOf-8-1!./node_modules/postcss-loader/src??postcss!./node_modules/resolve-url-loader??ref--6-oneOf-8-3!./node_modules/less-loader/dist/cjs.js??ref--6-oneOf-8-4!./src/styles.module.less)
ValidationError: Invalid options object. Less Loader has been initialized using an options object that does not match the API schema.
 - options has an unknown property 'options'. These properties are valid:
   object { lessOptions?, prependData?, appendData?, sourceMap? }

笔者修改了config-overrides.js:

const { override, addLessLoader } = require('customize-cra');

module.exports = override(
  addLessLoader({
    strictMath: true,
    noIeCompat: true,
    localIdentName: "[local]--[hash:base64:5]" // if you use CSS Modules, and custom `localIdentName`, default is '[local]--[hash:base64:5]'.
  }),
)

好了,运行成功,我们看见了红色Hellow world。
因为没有第一次运行时候的demo,所以,笔者并不确定问题具体出在哪,即便,按上面的步骤走,估计也会出错,因为less-loader更新了。。。
为此,笔者贴出自己实验的时候,所用依赖包的信息,仅供参考。

  "devDependencies": {
    "customize-cra": "^1.0.0-alpha.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "react-app-rewired": "^2.1.5"
  }

2.2.6 配置less(在react使用TypeScript语言下的优化–––去掉含module的后缀名)

修改config-overrides.js:

const { override, addLessLoader } = require('customize-cra');

module.exports = override(
  addLessLoader({
    strictMath: true,
    noIeCompat: true,
    javascriptEnabled: true,
    cssLoaderOptions: {
      modules: {localIdentName: '[name]_[local]_[hash:base64:5]'},
    }, // .less file used css-loader option, not all CSS file.
  }),
)

修改react-app-env.d.ts文件:

/// 

declare module "*.less"

最后,注意也要修改styles.less的文件名以及在indext.tsx的import路径。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2.2.6 扩展:引用CSS Module

新建文件styles.module.css

//styles.module.css
.title {
  color: blue;
}

修改index.js文件:

//index.js
import stylesCss from './styles.module.css'
//.......省略

Hello CSS Modules

//.......省略

运行,成功。

3. 总结

为了方便快速浏览,笔者对第二种比较优雅的配置方法,进行总结。如果上面部分已经看过了,这部分可以忽略,仅仅是对上面陈述的方法二的总结。

3.1 安装依赖

#安装less和less-loader
$yarn add less less-loader -D
#安装react-app-rewired
$yarn add react-app-rewired -D
#安装customize-cra 如果,你安装时的最新版本已经超过这个,可以不用指定版本
$yarn add customize-cra@^1.0.0-alpha.0 -D

3.2 修改package.json文件

//package.json
"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test --env=jsdom",
    "eject": "react-scripts eject"
  },

3.3 在项目根目录新建config-overrides.js

并对less进行配置:

//config-overrides.js
const { override, addLessLoader } = require('customize-cra');

module.exports = override(
  addLessLoader({
    strictMath: true,
    noIeCompat: true,
    loader: "css-loader",
    options: {
      modules: {
        localIdentName: "[name]__[local]___[hash:base64:5]",
      },
      sourceMap: true
    }
  }),
)

3.4 对于支持TypeScript的项目的配置

修改config-overrides.js:

const { override, addLessLoader } = require('customize-cra');

module.exports = override(
  
  addLessLoader({
    strictMath: true,
    noIeCompat: true,
    localIdentName: "[local]--[hash:base64:5]" // if you use CSS Modules, and custom `localIdentName`, default is '[local]--[hash:base64:5]'.
  }),
)

修改react-app-env.d.ts文件:

//react-app-env.d.ts
declare module "*.module.less"

3.5 对于支持TypeScript的项目的配置的优化(去掉.module的后缀)

修改config-overrides.js:

const { override, addLessLoader } = require('customize-cra');

module.exports = override(
  addLessLoader({
    strictMath: true,
    noIeCompat: true,
    javascriptEnabled: true,
    cssLoaderOptions: {
      modules: {localIdentName: '[name]_[local]_[hash:base64:5]'},
    }, // .less file used css-loader option, not all CSS file.
  }),
)

修改react-app-env.d.ts文件:

/// 

declare module "*.less"

最后,注意也要修改styles.less的文件名以及在indext.tsx的import路径。

3.6 测试

注意less文件命名规则,后缀为.module.less

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import styles from './styles.module.less' 

const App = () => {
  console.log(styles);//打印一下,是一个对象,对象的元素的key是title
  return(
    

Hello world

) } ReactDOM.render(, document.getElementById('root'));
//styles.module.less
.title {
  color: red;
}

3.7 纠错

笔者,在第二次补充的时候,发现又跑不起来了。经调查,发现是因为less-loader版本更新的原因,为此,笔者贴出测试的时候,所用依赖库的版本:

  "devDependencies": {
    "customize-cra": "^1.0.0-alpha.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "react-app-rewired": "^2.1.5"
  }

网上,查看各种文档都不好用的时候,包括笔者这篇也被淘汰的时候,建议你看看官网customize-cra API,这个是找答案最快捷的办法。

你可能感兴趣的:(React中使用less(use CSS Modules)的两种配置方法)