webpack-css

相关loader简说

style-loader: 将css样式插入到html中
css-loader: 处理@importurl相当于import/require,即将css当作模块引用处理,提供CSS-Modules方式,以及importLoaders(文档中没有太多说明,后面会贴一下找到的issues)
postcss-loader: 后处理,主要通过插件执行压缩/加浏览器前缀/可用下一代css语法/监听@import等等
less-loader: 或者其他的css预处理
从下到上有序执行

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
webpack.config.js

const path = require('path')
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
...
module.exports = {
...
module: {
rules: [
...
{
test: /\.less$/,
use: [
<!-- 'style-loader', 未区分开发/生产环境,demo直接用了css文件提取-->
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
<!-- 配置项有改动,及时到git上找相应版本配置 -->
<!-- 开启了module模式 -->
modules: {
mode: 'local',
localIdentName: '[path][name]__[local]--[hash:base64:5]'
},
localsConvention: "camelCase",
importLoaders: 2
}
},
'postcss-loader',
<!-- resolve-url-loader说是可以解决路径问题,可以转变成绝对路径,但是暂时没发现不用有啥问题,还是先加上了 -->
"resolve-url-loader",
"less-loader"
]
}
]
},
plugins: [
...
new MiniCssExtractPlugin()
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
postcss.config.js

module.exports = {
ident: 'postcss',
plugins: [
<!-- 监听了@import,可以使在less文件中引用css文件时先走postcss处理,css-loader的importLoaders同作用 -->
<!-- 在modules模式下,还可以处理在less文件中引用css文件时,正常将css文件中的局部样式一同export出去 -->
require("postcss-import")(),
<!-- require("autoprefixer")(), -->
<!-- 新版本替换了nextcss,同样包含autoprefixer -->
require("postcss-preset-env")(),
<!-- 压缩,可以删除重复代码 -->
require("cssnano")()
]
}

demo中混用了在less文件中引用css文件,测试能否正常将引用的css文件被loader处理,以及modules模式下是否正常,但是!!!实际情况还是不得会在less文件中引用css文件,如都一致使用预处理语言,不会出现任何坑,都正常按照loader顺序执行

1
2
3
4
5
6
7
8
base.less

...
@import "./main.css";
.test-moudles {
composes: box from "./main.css";
border: 1px solid black;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
main.css

...
/* for test importLoaders and postcss-import */
/* 直接引用css文件的情况,通过importLoaders或postcss-import均正常 */
:global(#root) {
transform: translate(100px,100px)
}
/* for test importLoaders and postcss-import */
/* modules方式下,直接引用css文件,通过postcss-import可将局部class正常被export出去 */
.test-moudles-main {
transform: translate(10px,10px)
}
/* for test composes */
.box {
border-color: pink;
background-color: pink;
transform: translate(5px,5px)
}
/* for test cssnano */
.box {
border-color: pink;
background-color: pink;
transform: translate(5px,5px)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
index.js

...
import style from "./css/base.less"
import img from './assets/image/sp/sp2/27.png'

const root = document.getElementById('root')

function cImg(){
const image = new Image()
image.src = img
<!-- image.classList.add(style.testMoudlesMain) -->
<!-- style.testMoudles包含两个class了,不能直接用add方法 -->
image.className = style.testMoudles + ' ' + style.testMoudlesMain
root.appendChild(image)
}
cImg()

先看下效果:

解释几点:
⚠️1⃣️ 非modules模式下,在less文件中引入css文件,css文件可以被postcss-loader处理,可通过postcss-import/importLoaders实现
⚠️2⃣️ modules模式下,光使用importLoaders不能抛出被引入的css文件中的局部class,但是composes可是正常使用,同时也能被postcss-loader处理,使用postcss-import没有以上问题,所以感觉postcss-import很有用。但是webpack文档中有特意描述说开启modules的时候需要加importLoaders,但是并没有描述清楚在解决什么问题,甚至importLoaders相关说明也不多,也有人提issue,我大概看了下貌似是解决上面的1⃣️问题,如图:


但是webpack这里描述开启modules是加上importLoaders没找到解释
然后在css-loader的readme上看到说importLoaders会有变化,好像只是个临时的结局方案的味道

so,目前了解到的就这么多,有postcss-import已解决了出现的问题

CSS-Modules

记录一下css-loader开启的modules本质方式:重新命名设置的class名称,并export出去一个对象,key是原class名称,value是新class名称,在js中import后通过原class名称调用出新class使用即可

:global(classname)代表全部样式,不会被转换class名称
:local(classname)显示声明局部样式class,不写标签注明的默认是局部样式

比较好的博客链接:里面有提到Stylelint马一下这里有提到resolve-url-loader和css去重css-loader
代码地址:demo