likes
comments
collection
share

webpack入门之css处理(css预处理器和css后置处理器)

作者站长头像
站长
· 阅读数 19

本文 webpack 版本 ^5.73.0、webpack-cli 版本 ^4.10.0

简介

说到前端构建就肯定离不开css的处理。在前端日新月异的潮流下,css也不再是单纯的css了,涌现了很多css周边技术,比如我们常听到的css预处理器(PreCss)css后置处理器(PostCss)。那这两个东西又是啥呢?他们的区别又是什么呢?以及在webpack中又怎么去处理它呢?

带着疑问,我们今天就来一探究竟

看完本文你将学到:

  1. 知道什么是css预处理器
  2. css预处理器都有哪些
  3. css预处理器有哪些作用
  4. css预处理器怎么编译成css
  5. 知道什么是css后置处理器
  6. css后置处理器有哪些作用
  7. css后置处理器是怎么处理css的
  8. 怎么使用webpack来处理css预处理器和css后置处理器
  9. 编译适配目标浏览器的配置 browserslist

css预处理器PreCss

为什么会出现CSS预编译器这个东西呢?这就要谈到CSS的不足了:

  1. 没有变量(新的规范已经支持了)。
  2. 不支持嵌套。
  3. 编程能力较弱,代码复用性差。
  4. 没有模块化。

为了弥补这些不足之处,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

LessCSS的一种扩展形式,在CSS语法基础上添加了很多额外功能。从语法规则来讲,LessScss一样,都是用CSS的标准语法,只是Less的源文件扩展名是.less,举个栗子🌰:

.block {
    height: 30px;
    padding-bottom: 10px;
    color: #666;
    font-weight: normal;
}

更多特性可自行查看less中文文档学习。

stylus

Stylus语法多变一些,文件扩展名是.stylStylus既接受标准的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文件

webpack入门之css处理(css预处理器和css后置处理器)

安装完后它会提供一个sass命令,使用该命令就可以将.scss文件编译成.css文件了。

sass styles.scss styles.css

我们来看下编译后的效果

webpack入门之css处理(css预处理器和css后置处理器)

less

编译less首先需要安装less

npm install -g less

然后我们创建styles.less文件

webpack入门之css处理(css预处理器和css后置处理器)

安装完后它会提供一个lessc命令,使用该命令就可以将.less文件编译成.css文件了。

lessc styles.less styles.css

我们来看下编译后的效果

webpack入门之css处理(css预处理器和css后置处理器)

stylus

编译stylus首先需要安装stylus

npm install -g stylus

然后我们创建styles.styl文件

webpack入门之css处理(css预处理器和css后置处理器)

安装完后它会提供一个stylus命令,使用该命令就可以将.styl文件编译成.css文件了。

stylus styles.styl -o styles.css

我们来看下编译后的效果

webpack入门之css处理(css预处理器和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

webpack入门之css处理(css预处理器和css后置处理器)

然后在里面分别添加内容

index.less

webpack入门之css处理(css预处理器和css后置处理器)

index.scss

webpack入门之css处理(css预处理器和css后置处理器)

index.styl

webpack入门之css处理(css预处理器和css后置处理器)

并在入口文件index.js里面引入我们的样式文件

webpack入门之css处理(css预处理器和css后置处理器)

安装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-loadercss-loader解析后的样式代码内联插入到HTML中的style标签内。

配置编译脚本

然后我们在package.json里面创建运行webpack的脚本

"scripts": {
  "webpack1": "webpack"
},

运行脚本

然后我们运行npm run webpack1webpack会读取webpack.config.js文件,进行打包。

默认会读取根目录的src文件夹,默认将打包结果放到根目录dist文件夹下。

运行打包命令后我们可以看到,在根目录下生成了dist文件夹,并输出了main.js

webpack入门之css处理(css预处理器和css后置处理器)

看效果

编译后的文件是很混乱的,不容易看懂,所以我们需要测试刚才的样式是否成功。

我们首先在根目录下创建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>

然后在浏览器运行,我们来看看效果

webpack入门之css处理(css预处理器和css后置处理器)

nice! 至此使用webpack构建less、scss、stylus就完成啦。

将css抽离成单独的css文件

前面说到,style-loader的作用是将处理好后的CSS样式代码放到HTMLstyle标签中。

webpack入门之css处理(css预处理器和css后置处理器)

那么,如果我需要将处理后的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文件。

webpack入门之css处理(css预处理器和css后置处理器)

最后我们在index.html文件中手动引入main.css就可以了。

<link rel="stylesheet" href="./dist/main.css" />

可能有些小伙伴觉得,自己每次手动引入jscss太麻烦,有没有自动引入的方式呢?这就需要用到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文件

webpack入门之css处理(css预处理器和css后置处理器)

并且该文件自动引入了我们构建后的jscss文件

webpack入门之css处理(css预处理器和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 VariablesMixins, 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,以及其它很多优秀的功能。

笔者简单理解postcsscsstranspiler(转换编译器,简称转译器),它对于 css 就像 babel 对于 js 一样,能够做 css 代码的分析和转换。同时,它也提供了插件机制来做自定义的转换。

普通构建

我们这里拿autoprefixer插件来做例子来讲解。

创建项目

首先我们创建一个文件夹,然后初始化package.json文件。

// 创建webpacktest文件夹
mkdir postcsstest

// 进入postcsstest文件夹
cd postcsstest

// 创建package.json
npm init

创建源文件

因为我们要测试autoprefixer,所以我们需要找一个需要带浏览器前缀的样式。这个修改placeholder颜色的样式刚刚好。

webpack入门之css处理(css预处理器和css后置处理器)

安装 postcss、postcss-cli

单独使用postcss我们需要安装postcss、postcss-cli。这样我们就可以在命令行使用postcss命令了。

npm i postcss postcss-cli -D

安装插件

npm i autoprefixer -D

创建 postcss.config.js

postcss.config.jspostcss的配置文件,我们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前缀的样式。

webpack入门之css处理(css预处理器和css后置处理器)

这里我们只拿autoprefixer作了讲解,其实截止到目前,PostCSS200 多个插件。你可以在 插件列表找到它们。这些插件我们可以在不同需求下选择使用。

使用postcss-cli构建虽然可以,但是不推荐这么使用。一般我们都是使用webpack进行前端统一构建,所以下面笔者来说说使用webpack来构建我们的postcss

使用webpack构建

这里我们就不再单独创建项目了,我们基于前面预处理器的webpacktest项目。

创建源文件

我们把前面创建好的post1.css文件复制过来,并在入口文件index.js里面引入

webpack入门之css处理(css预处理器和css后置处理器)

安装 postcss-loader

webpack里面使用postcss,我们只需要安装postcss-loader就可以了。

npm i postcss-loader -D

安装插件

npm i autoprefixer -D

创建 postcss.config.js

postcss.config.jspostcss的配置文件,我们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

webpack入门之css处理(css预处理器和css后置处理器)

运行脚本

接下来我们编译下,npm run webpack1webpack会读取webpack.config.js文件,进行打包。

看效果

我们来看看编译后的代码,发现它也自动生成了-moz前缀的样式。

webpack入门之css处理(css预处理器和css后置处理器)

在页面上可以看到,我们inputplaceholder的颜色被我们改成红色了。

webpack入门之css处理(css预处理器和css后置处理器)

好奇

为什么每次只生成了火狐浏览器的前缀-moz呢?不是还有ie浏览器前缀-mschrome浏览器前缀-webkit吗?

按理来说不应该是生成下面这些样式吗

webpack入门之css处理(css预处理器和css后置处理器)

这里就需要了解另外一个知识点了,那就是browserslist

那这个browserslist到底是什么东西呢?

简单理解,browserslist 实际上就是声明了⼀段浏览器的集合,我们的⼯具可以根据这段集合描述,针对性的输出兼容性代码。

.browserslistrc文件的默认值是

> 0.5%
last 2 versions
Firefox ESR
not dead

所以,当我们不配置browserslist的话,它的配置就是上面的默认配置,所以并不会生成所有浏览器的前缀,只会针对性的输出。

如果想输出全部怎么办呢?我们可以做一个小测试,我们把not dead注释掉,再编译。

webpack入门之css处理(css预处理器和css后置处理器)

可以看到,编译后的文件里面有所有浏览器的前缀了。

webpack入门之css处理(css预处理器和css后置处理器)

我们除了定义.browserslistrc文件来配置browserslist外,我们还可以直接配置在package.json文件中,通过browserslist键来配置。

// package.json
{
  "browserslist": [
    "last 1 version",
    "> 1%",
    "IE 10"
  ]
}

现在对browserslist有了一个大概的了解了吧。

总结

好啦,看了上面的例子,小伙伴们应该很清楚css预处理器(PreCss)和css后置处理器(PostCss)了吧。

总的来说,css预处理器是用来弥补css不足的,它提供了变量、嵌套、复用、模块等方案,让我们的开发效率和开发体验大大提升。缺点是浏览器不能直接识别,每次上线前需要我们单独进行编译。

css后置处理器是用来处理css的,postcsscsscss 的转译器,它分为 parse、transform、generate 3个阶段。各种转换插件都是工作在 transform 阶段,基于 AST 做分析和转换。

webpack入门之css处理(css预处理器和css后置处理器)

系列文章

后记

感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!