Fork me on GitHub

webpack4笔记(4)-处理css

CSS基础处理

webpack中关于css的处理用到两个loader:

  • css-loader: 用于处理css文件中的@import和url(…)
  • style-loader: 将css-loader的输出生成js中的函数调用将css动态添加到html文件中。
1
yarn add css-loader style-loader -D
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
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
},
devServer: {
contentBase: './dist',
hot: true
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
tempalte: './src/index.html',
filename: 'index.html'
})
]
}

运行yarn start可以看到页面变成了粉色,运行yarn build可以看到一个html文件和一个js文件,css被打包到js文件中了

分离CSS文件

style-loader将css动态添加到html文件中,生产环境下我们希望将所有的css抽离为独立的css文件,此时可以借助mini-css-extract-plugin

1
yarn add mini-css-extract-plugin -D

将style-loader改为mini-css-extract-plugin的loader:

1
2
3
4
5
6
7
8
9
...
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

...
{
test: /\.css$/,
use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
}
...

另外,还需要引入MiniCssExtractPlugin插件本身:

1
2
3
4
5
6
7
plugins: [
...
new MiniCssExtractPlugin({
filename: "[name].[hash].css",
chunkFilename: "[name].[hash].css"
})
]

运行yarn build可以看到生成了独立的main.ec3a0b2de01cd68066ac.css,并且在index.html文件中自动引入了该css文件。

CSS Modle

所有的class的名称和动画的名称默认属于本地作用域的CSS文件。
所以CSS Modules不是一个官方的规范,也不是浏览器的一种机制,它是一种构建步骤中的一个进程。(构建通常需要webpack或者browserify的帮助)。通过构建工具的帮助,可以将class的名字或者选择器的名字作用域化。(类似命名空间化。)目的在于解决CSS中的全局作用域问题。

CSS Module只对类名和动画的名字起作用,css-loader支持CSS Module,CSS Module为每个独立的css文件处理为一个module。此时需要修改webpack.config.js文件中css-loader的配置:

1
2
3
4
5
6
7
8
{
loader: 'css-loader',
options: {
sourceMap: true,
modules: true, // 表示启用CSS Module
localIdentName: '[name]---[local]---[hash:base64:5]' // 设置css类名的命名方式。
}
}

在main.css中加入更多的css:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
body {
background-color: pink;
}

div {
box-sizing: border-box;
}

.red {
background-color: red;
}

// :global表示脱离模块化约束而使用全局的声明(即效果跟普通css相同)
:global(.gold){
background-color: gold;
}

// :local表示使用模块化化处理
:local(.aqua){
background-color: aqua;
}

⚠️注意:这里的:local有点多余,因为当启用了CSS Module之后,css文件中的类名默认便是:local的。

运行 yarn build 结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
body {
background-color: pink;
}

div {
box-sizing: border-box;
}

.index---red---3fvh6 {
background-color:red;
}

.gold{
background-color:gold;
}


.index---aqua---3SX9z{
background-color: aqua;
}

.main—red—1GVbX对应原文件中的.red,命名规则有localIdentName: ‘[name]—[local]—[hash:base64:5]’配置完成。.gold由于标记有:global,所以生成的全局的类名。

使用SASS

Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更加强大与优雅。使用 Sass 以及 Sass 的样式库(如 Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。

文档:https://www.sass.hk/docs/

1
yarn add sass-loader node-sass -D

⚠️注意需要安装node-sass

修改rules,让原来处理的css的loader也能处理scss文件:

1
2
3
...
test: /\.(s*)css$/,
...

然后加入sass-loader:

1
2
3
4
5
6
7
8
...
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
...

⚠️注意:sass-loader需要是处理scss/css文件的第一个loader,需要配置在最后面。

src目录下创建base.scss

1
2
3
4
5
6
7
body {
background-color: red;
}

div {
box-sizing: border-box;
}

global.scss

1
$base-color: pink;

main.scss,通过@import引入global.scss、base.scss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@import './global.scss';
@import './base.scss';

:global(.gold){
background-color:gold;
}


:local(.aqua){
background-color: aqua;
}

.localRed {
background-color: $base-color;
}

main1.scss,通过@import引入global.scss、base.scss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@import './global.scss';
@import './base.scss';

:global(.gold){
background-color:gold;
}


:local(.aqua){
background-color: aqua;
}

.localRed {
background-color: $base-color;
}

在index.js文件中引入base.scss,main.scss,main1.scss

运行 yarn build,输出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
body {
background-color: red; }

div {
box-sizing: border-box; }

body {
background-color: red; }

div {
box-sizing: border-box; }

.gold {
background-color: gold; }

.main---aqua---Faovj {
background-color: aqua; }

.main---localRed---2p9T9 {
background-color: pink; }

body {
background-color: red; }

div {
box-sizing: border-box; }

.gold {
background-color: gold; }

.main1---aqua---34bRO {
background-color: aqua; }

.main1---localRed---1uPXQ {
background-color: pink; }

可以看到base.scss中的内容出现了三次,因为SASS分别以这三个文件为编译单位进行处理,最后将他们的内容合并到一起。

因此对于SASS来说,有个原则是如果有文件作为公共css文件,那么建议它最多只引用1次,通常是在入口文件中进行引用,比如VueJS的App.vue文件。

PostCSS

1
yarn add postcss-loader -D

添加postcss-loader,并且添加autoprefixer插件:

1
yarn add autoprefixer -D
1
2
3
4
5
6
7
{
loader: 'postcss-loader',
options: {
plugins: [require("autoprefixer")],
sourceMap: true
}
}

然后在package.json中添加:

1
2
3
4
5
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]

运行 yarn build 发现base.scss中的div添加了后缀

1
2
3
div {
-webkit-box-sizing: border-box; // autoprefixer自动加上的前缀。
box-sizing: border-box; }

多入口项目CSS处理

当项目中有多个入口文件时,webpack会为每个入口文件生成对应的css bundle文件。

演示一下,src目录下创建index1.html,index2.html文件,创建模块common.js,让两个入口文件都依赖于该模块:

1
2
3
4
import './common.scss'
export function log () {
console.log('common module');
}

common.scss

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
.blue {
background-color: blue;
}

.yellow {
background-color: yellow;
}

.green {
background-color: green;
}

.gray {
background-color:gray;
}


:global(.deepskyblue){
background-color:deepskyblue;
}


:local(.fuchsia){
background-color: fuchsia;
}

创建index1.js

1
2
3
4
import { log } from './common.js'

log('index1.1');
log('index1.2');

index2.js

1
2
3
4
import { log } from './common.js'

log('index2.1');
log('index2.2');

运行 yarn build 可以看到webpack为两个入口文件分别生成了css bundle文件。

合并css文件

有时我们需要将真个项目中所有生成的css合并为一个文件,此时可以使用splitChunks:

1
2
3
4
5
6
7
8
9
10
11
12
13
splitChunks: {
cacheGroups: {
default: false,
vendors: false,

styles: {
name: 'styles',
test: /\.(s*)css$/,
chunks: 'all',
enforce: true
}
}
}

修改HtmlWebpackPlugin配置,使每个入口文件引用自己的bundle以及公共的styles chunk文件:

1
2
3
4
5
6
7
8
9
10
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
chunks: ['styles']
}),
new HtmlWebpackPlugin({
template: './src/index2.html',
filename: 'index2.html',
chunks: ['styles']
}),

可以看到只生成一个styles.a5178a5acb27551c5dde.css

本文标题:webpack4笔记(4)-处理css

文章作者:tongtong

发布时间:2019年04月23日 - 19:04

最后更新:2019年04月24日 - 16:04

原始链接:https://ilove-coding.github.io/2019/04/23/webpack4笔记(4)-处理css/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!
-------------本文结束-------------