webpack入门之css处理(css预处理器和css后置处理器)
本文 webpack 版本 ^5.73.0、webpack-cli 版本 ^4.10.0
简介
说到前端构建就肯定离不开css
的处理。在前端日新月异的潮流下,css
也不再是单纯的css
了,涌现了很多css
周边技术,比如我们常听到的css预处理器(PreCss)
和css后置处理器(PostCss)
。那这两个东西又是啥呢?他们的区别又是什么呢?以及在webpack
中又怎么去处理它呢?
带着疑问,我们今天就来一探究竟
看完本文你将学到:
- 知道什么是css预处理器
- css预处理器都有哪些
- css预处理器有哪些作用
- css预处理器怎么编译成css
- 知道什么是css后置处理器
- css后置处理器有哪些作用
- css后置处理器是怎么处理css的
- 怎么使用webpack来处理css预处理器和css后置处理器
- 编译适配目标浏览器的配置 browserslist
css预处理器PreCss
为什么会出现CSS
预编译器这个东西呢?这就要谈到CSS
的不足了:
- 没有变量(新的规范已经支持了)。
- 不支持嵌套。
- 编程能力较弱,代码复用性差。
- 没有模块化。
为了弥补这些不足之处,CSS
预编译器应运而生。而谈到CSS
预编译器,就离不开这三剑客Sass、Less、Stylus
。
历史上,最先登场的是Sass
,因为出现最早,所以也是最完善的,有各种丰富的功能;Less
的出现伴随着Bootstrap
的流行,因此也获得大量用户;最后是Stylus
,由TJ大神开发(敬大神),由于其简洁的语法,更像是一门编程语言,写起来非常Cool
。所以下面我们来做一个简单的对比。
scss
Sass3.0
版本开始使用的是标准的CSS
语法,基本与SCSS
一样。默认Sass
使用.scss
扩展名。
// scss新版语法规则
.container {
background: #f6f6f6;
min-height: 100%;
}
同时,Sass
也支持老的语法,这种跟常规的CSS
略有不同,更为严格,任何的缩进和字符的错误都会造成样式的编译错误,Sass
可以省略{}
和;
,而且文件使用.sass
扩展名,语法如下:
.container
background: #f6f6f6
min-height: 100%
更多特性可自行查看sass中文文档学习。
less
Less
是CSS
的一种扩展形式,在CSS
语法基础上添加了很多额外功能。从语法规则来讲,Less
和Scss
一样,都是用CSS
的标准语法,只是Less
的源文件扩展名是.less
,举个栗子🌰:
.block {
height: 30px;
padding-bottom: 10px;
color: #666;
font-weight: normal;
}
更多特性可自行查看less中文文档学习。
stylus
Stylus
语法多变一些,文件扩展名是.styl
,Stylus
既接受标准的CSS
语法,也可以跟Sass
老的语法规则一样,使用缩进控制,如下所示:
// 类似于CSS标准语法
.head {
color: #ebebeb;
background-color: #666;
}
// 省略大括号
.head
color: #ebebeb;
background-color: #666;
// 省略大括号和分号
.head
color: #ebebeb
background-color: #666
更多特性可自行查看less中文文档学习。
普通构建
说了这么多css
预处理器,预处理器代码能在浏览器运行吗?这些语法能被浏览器直接识别吗?
当然是不能的,所以在正式上线之前我们都需要进行编译,也就是把这些.scss、.less、.styl
文件转变成浏览器能识别的.css
文件。
那我们怎么进行编译呢?这就需要用到对应的工具了。
sass
编译sass
首先需要安装sass
。
npm install -g sass
然后我们创建styles.scss
文件
安装完后它会提供一个sass
命令,使用该命令就可以将.scss
文件编译成.css
文件了。
sass styles.scss styles.css
我们来看下编译后的效果
less
编译less
首先需要安装less
。
npm install -g less
然后我们创建styles.less
文件
安装完后它会提供一个lessc
命令,使用该命令就可以将.less
文件编译成.css
文件了。
lessc styles.less styles.css
我们来看下编译后的效果
stylus
编译stylus
首先需要安装stylus
。
npm install -g stylus
然后我们创建styles.styl
文件
安装完后它会提供一个stylus
命令,使用该命令就可以将.styl
文件编译成.css
文件了。
stylus styles.styl -o styles.css
我们来看下编译后的效果
上面的编译笔者都是全局安装的,当然你也可以局部安装。
我们可以看到,css
预处理器虽然好用,但是每次上线都需要我们手动打包成css
,然后再发布是不是有点麻烦。有没有什么更好更高效的办法呢?
当然是有的,我们可以借助webpack
,在上线前统一编译即可。下面笔者就来说说使用webpack
来编译这三个css
预处理器。
使用webpack构建
创建项目
首先我们创建一个文件夹,然后初始化package.json
文件。
// 创建webpacktest文件夹
mkdir webpacktest
// 进入webpacktest文件夹
cd webpacktest
// 创建package.json
npm init
创建scss、less、stylus源文件
接下来我们创建scss、less、stylus
源文件,在根目录下创建src
文件夹,在里面分别创建index.scss、index.less、index.styl
然后在里面分别添加内容
index.less
index.scss
index.styl
并在入口文件index.js
里面引入我们的样式文件
安装webpack 和 webpack-cli
接下来我们本地安装webpack 和 webpack-cli
npm i webpack webpack-cli -D
安装处理scss、less、stylus的loader
因为webpack
默认只能处理js
,如果需要处理其他语言的话需要安装对应的loader
,这里我们需要分别安装处理scss、less、stylus
文件的less、less-loader、node-sass、sass-loader、stylus、stylus-loader
npm i less less-loader node-sass sass-loader stylus stylus-loader -D
安装处理css的loader
当然,css
也是需要处理的,所以也需要对应的loader
。
npm i css-loader style-loader -D
配置webpack.config.js
然后我们在根目录下创建webpack.config.js
文件,并做如下配置
module.exports = {
mode: "development",
module: {
rules: [
// Less 配置
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
// Sass 配置
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
// stylus 配置
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
],
},
};
loader
的配置是有顺序要求的,它的执行顺序是从右到左的。比如use: ['style-loader', 'css-loader']
,它先用css-loader
处理CSS
的模块化,然后style-loader
把css-loader
解析后的样式代码内联插入到HTML
中的style
标签内。
配置编译脚本
然后我们在package.json
里面创建运行webpack
的脚本
"scripts": {
"webpack1": "webpack"
},
运行脚本
然后我们运行npm run webpack1
,webpack
会读取webpack.config.js
文件,进行打包。
默认会读取根目录的src
文件夹,默认将打包结果放到根目录dist
文件夹下。
运行打包命令后我们可以看到,在根目录下生成了dist
文件夹,并输出了main.js
看效果
编译后的文件是很混乱的,不容易看懂,所以我们需要测试刚才的样式是否成功。
我们首先在根目录下创建index.html
,并引入构建好的main.js
文件,然后创建三个div
,分别引用刚才的样式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>webpack</title>
</head>
<body>
<div class="box1">less test</div>
<div class="box2">scss test</div>
<div class="box3">stylus test</div>
<script src="./dist/main.js"></script>
</body>
</html>
然后在浏览器运行,我们来看看效果
nice! 至此使用webpack
构建less、scss、stylus
就完成啦。
将css抽离成单独的css文件
前面说到,style-loader
的作用是将处理好后的CSS
样式代码放到HTML
的style
标签中。
那么,如果我需要将处理后的CSS
文件单独编译成一个.css
文件,引入到HTML
中,webpack
需要怎么做呢?
我们可以使用mini-css-extract-plugin
插件提取css
代码为单独的CSS
文件,然后在HTML
中通过link
标签引入CSS
文件。
npm install mini-css-extract-plugin -D
然后我们使用MiniCssExtractPlugin.loader
来替换style-loader
// 1.引入
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: "development",
module: {
rules: [
// Less 配置
{
test: /\.less$/,
// use: ["style-loader", "css-loader", "less-loader"],
// 3. 替换style-loader
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
// Sass 配置
{
test: /\.scss$/,
// use: ["style-loader", "css-loader", "sass-loader"],
// 3. 替换style-loader
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
// stylus 配置
{
test: /\.styl$/,
// use: ["style-loader", "css-loader", "stylus-loader"],
// 3. 替换style-loader
use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
},
],
},
// 2. 实例化插件
plugins: [new MiniCssExtractPlugin()],
};
然后我们重新构建,可以发现,编译后的css
会单独形成一个main.css
文件。
最后我们在index.html
文件中手动引入main.css
就可以了。
<link rel="stylesheet" href="./dist/main.css" />
可能有些小伙伴觉得,自己每次手动引入js
和css
太麻烦,有没有自动引入的方式呢?这就需要用到html-webpack-plugin
插件啦
自动引入js和css文件
首先安装
npm install html-webpack-plugin -D
然后在webpack.config.js
使用该插件。
// 1.引入
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 1.引入
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "development",
// ...
// 2. 实例化插件
plugins: [
new HtmlWebpackPlugin({
// 模板html文件的位置,我们这里是在根目录下
template: "./index.html",
}),
new MiniCssExtractPlugin(),
],
};
然后我们重新编译,可以看到在dist
文件夹下多了index.html
文件
并且该文件自动引入了我们构建后的js
和css
文件
自动清空打包目录
每次打包的时候,打包目录都会遗留上次打包的文件,为了保持打包目录的纯净,我们需要在打包前将打包目录清空
这里我们可以使用插件 clean-webpack-plugin
来实现。
老规矩,首先安装
npm install clean-webpack-plugin -D
然后在webpack.config.js
使用该插件。
// 1.引入
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 1.引入
const HtmlWebpackPlugin = require("html-webpack-plugin");
// 1.引入
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
mode: "development",
// 使用CleanWebpackPlugin需要显示定义出口,不然无效
output: {
filename: "[name].js",
path: path.resolve(__dirname, "./dist"),
},
// ...
// 2. 实例化插件
plugins: [
new HtmlWebpackPlugin({
// 模板html文件的位置,我们这里是在根目录下
template: "./index.html",
}),
new MiniCssExtractPlugin(),
new CleanWebpackPlugin(),
],
};
然后我们再次打包,可以发现,它会先将dist
目录删除,然后重新生成dist
目录。
css
的前置处理器我们大致讲完了,接下来我们再来说说css
的后置处理器。
css后置处理器PostCss
对于 PostCSS 官方的解释是: PostCSS
是一个允许使用 JS
插件转换样式的工具。 这些插件可以检查(lint)你的 CSS
,支持 CSS Variables
和 Mixins
, 编译尚未被浏览器广泛支持的先进的 CSS
语法,内联图片,以及其它很多优秀的功能。
笔者简单理解postcss
是 css
的 transpiler
(转换编译器,简称转译器),它对于 css
就像 babel
对于 js
一样,能够做 css
代码的分析和转换。同时,它也提供了插件机制来做自定义的转换。
普通构建
我们这里拿autoprefixer
插件来做例子来讲解。
创建项目
首先我们创建一个文件夹,然后初始化package.json
文件。
// 创建webpacktest文件夹
mkdir postcsstest
// 进入postcsstest文件夹
cd postcsstest
// 创建package.json
npm init
创建源文件
因为我们要测试autoprefixer
,所以我们需要找一个需要带浏览器前缀的样式。这个修改placeholder
颜色的样式刚刚好。
安装 postcss、postcss-cli
单独使用postcss
我们需要安装postcss、postcss-cli
。这样我们就可以在命令行使用postcss
命令了。
npm i postcss postcss-cli -D
安装插件
npm i autoprefixer -D
创建 postcss.config.js
postcss.config.js
是postcss
的配置文件,我们postcss
的配置都需要在这里定义。
前面我们安装了autoprefixer
插件,这里我们再来配置下。
// postcss.config.js
// 引入
const autoprefixer = require("autoprefixer");
module.exports = {
// 使用
plugins: [autoprefixer],
};
配置编译脚本
然后我们在package.json
里面创建运行postcss
的脚本
"scripts": {
"pc1": "postcss src/post1.css -o dist/post1.css"
},
运行脚本
我们运行上面配置好的脚本来编译下,npm run pc1
。当我们在命令行运行该命令时,其实真实运行的是postcss src/post1.css -o dist/post1.css
,这样他会处理我们前面的post1.css
。
看效果
我们来看下dist/post1.css
,我们可以看到,它自动生成了-moz
前缀的样式。
这里我们只拿autoprefixer
作了讲解,其实截止到目前,PostCSS
有 200
多个插件。你可以在 插件列表找到它们。这些插件我们可以在不同需求下选择使用。
使用postcss-cli
构建虽然可以,但是不推荐这么使用。一般我们都是使用webpack
进行前端统一构建,所以下面笔者来说说使用webpack
来构建我们的postcss
使用webpack构建
这里我们就不再单独创建项目了,我们基于前面预处理器的webpacktest
项目。
创建源文件
我们把前面创建好的post1.css
文件复制过来,并在入口文件index.js
里面引入
安装 postcss-loader
在webpack
里面使用postcss
,我们只需要安装postcss-loader
就可以了。
npm i postcss-loader -D
安装插件
npm i autoprefixer -D
创建 postcss.config.js
postcss.config.js
是postcss
的配置文件,我们postcss
的配置都需要在这里定义。
前面我们安装了autoprefixer
插件,这里我们再来配置下。
// postcss.config.js
// 引入
const autoprefixer = require("autoprefixer");
module.exports = {
// 使用
plugins: [autoprefixer],
};
配置webpack.config.js
我们在rules
里面添加css
的处理规则。并配置上postcss-loader
。
module.exports = {
mode: "development",
module: {
rules: [
// css 配置
{
test: /\.css$/,
use: ["style-loader", "css-loader", "postcss-loader"],
},
// ...
],
},
};
修改index.html
我们在模板index.html
里面添加一个input
运行脚本
接下来我们编译下,npm run webpack1
。webpack
会读取webpack.config.js
文件,进行打包。
看效果
我们来看看编译后的代码,发现它也自动生成了-moz
前缀的样式。
在页面上可以看到,我们input
的placeholder
的颜色被我们改成红色了。
好奇
为什么每次只生成了火狐浏览器的前缀-moz
呢?不是还有ie
浏览器前缀-ms
,chrome
浏览器前缀-webkit
吗?
按理来说不应该是生成下面这些样式吗
这里就需要了解另外一个知识点了,那就是browserslist。
那这个browserslist
到底是什么东西呢?
简单理解,browserslist
实际上就是声明了⼀段浏览器的集合,我们的⼯具可以根据这段集合描述,针对性的输出兼容性代码。
.browserslistrc
文件的默认值是
> 0.5%
last 2 versions
Firefox ESR
not dead
所以,当我们不配置browserslist
的话,它的配置就是上面的默认配置,所以并不会生成所有浏览器的前缀,只会针对性的输出。
如果想输出全部怎么办呢?我们可以做一个小测试,我们把not dead
注释掉,再编译。
可以看到,编译后的文件里面有所有浏览器的前缀了。
我们除了定义.browserslistrc
文件来配置browserslist
外,我们还可以直接配置在package.json
文件中,通过browserslist
键来配置。
// package.json
{
"browserslist": [
"last 1 version",
"> 1%",
"IE 10"
]
}
现在对browserslist
有了一个大概的了解了吧。
总结
好啦,看了上面的例子,小伙伴们应该很清楚css
预处理器(PreCss)和css
后置处理器(PostCss)了吧。
总的来说,css
预处理器是用来弥补css
不足的,它提供了变量、嵌套、复用、模块等方案,让我们的开发效率和开发体验大大提升。缺点是浏览器不能直接识别,每次上线前需要我们单独进行编译。
css
后置处理器是用来处理css
的,postcss
是 css
到 css
的转译器,它分为 parse、transform、generate
3个阶段。各种转换插件都是工作在 transform
阶段,基于 AST
做分析和转换。
系列文章
后记
感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!
转载自:https://juejin.cn/post/7125605683633848356