打包CSS资源
前面说过,webpack只能识别js和json作为模块,如果你在代码中引入css无法识别并报错。
配置css-loader
这里介绍CSS的loader,因为最常用:
body {
background-color: black;
}
// 下载css-loader的包
const MODULE = {
rules: [
{
test: /\.css$/, // 匹配以.css结尾的文件
use: ['css-loader'], // 使用 css-loader 处理
}
]
}
打包发现,诶为啥css没有生效?
css-loader只负责识别css语法并支持模块化,import style from 'xx.css' 文件发现,style输出一个数组,css-loader确实已经帮我们完成了模块的转化!
// 第一元素是
[
'./src/assets/css/global.css',
'body {\n background-color: black;\n}',
''
]
哦,原来如此,css-loader只是完成了转换和识别(模块化),但是真正作用到页面需要将CSS插入到页面上,这个功能需要其它的loader帮助我们完成。
内联style插入样式
style-loader就是专门做这件事(将css-loader打包结果插入到html)的loader
// 下载style-loader的包
const MODULE = {
rules: [
{
test: /\.css$/, // 匹配以.css结尾的文件
use: ['style-loader', 'css-loader'], // 先使用 css-loader 处理,在经过style-loader动态创建style标签插入到页面里
}
]
}
打包发现,生效了,但是我们发现style这个变量的值变成了 undefined,因为style-loader最后处理完之后没有返回任何东西(它不需要对外暴露任何东西)
外联打包成单独的文件link链入样式
mini-css-extract-plugin提供了一个loader方法属性,MiniCssExtractPlugin.loader 简单的处理一下 css-loader 转换的对象
// 抽离css; extract => 提取 +++
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const MODULE = {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
}
]
}
// 加入 plugins
let plugins = [
...plugins,
new MiniCssExtractPlugin({
// 传入打包的各种配置
filename: 'style/[name][contenthash:8].css'
}),
]
兼容低版本的浏览器 CSS前缀
postcss是一个css预处理器,能够增强css的功能,但是它又不像less、sass那样,而是集成在webpack中,postcss有很多功能,为了细化功能,它将一个个功能细化为plugin,因此,当我们需要一些功能的时候需要安装对应的插件列表:
- autoprefixer 自动添加前缀
- postcss-nested 支持css嵌套写法
// webpack.config.js
let loaderRules = [
...loaderRules,
{
test: /\.css$/,
use: [
'style-loader', {
loader: 'css-loader',
// 假设一个css写了 @import ...,那么postcss-loader不会处理,等到了css-loader的时候,css-loader才开始识别到了 是另外的一个模块,但是 css-loader 无法为现在匹配到的 @import ... 用 postcss-loader,因此为了让 css-loader匹配到别的css模块的时候,回头n次,再顺序执行loader。这里回头一次就是 postcss-loader
importLoaders: 1,
},
'postcss-loader'
],
}
]
/*
不过需要注意的是,options.importLoaders需要考虑是否设置对应的值
[css-loader-importLoaders](https://github.com/webpack-contrib/css-loader#importloaders)
*/
// create postcss.config.js
module.exports = {
// 记得 npm i -D 一下
plugins: [
require('autoprefixer'),
require('postcss-nested')
]
}
npx webpack 打包发现确实可以支持嵌套写法的,但是autoprefixer为啥没生效?postcss-autoprefixer
我们的在package.json下面添加配置:
{
"browserslist": [
">1%",
"last 2 versions"
]
}
/* 如果你需要设置环境的话需要 cross-env */
// {
// "browserslist": {
// "production": [
// ">0.2%",
// "not dead",
// "not op_mini all"
// ],
// "development": [
// "last 1 chrome version",
// "last 1 firefox version",
// "last 1 safari version",
// "last 1 ie version"
// ]
// }
// }
CSS模块化
CSS Module 由css-loader支持,配置css-loader的options的
let cssLoader = {
loader: 'css-loader',
options: {
modules: true,
}
}
其实css-loader可以对以 .module.css结尾的文件自动的开启module模块化功能。
压缩CSS资源
js可以压缩,那么CSS肯定也可以,压缩都是通过插件,那么CSS的压缩插件:
// 压缩css
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const optimization = {
minimize: true, // 这个必须为true,当然默认是true,可以根据不同的环境考虑是否需要压缩
minimizer: [
new CssMinimizerPlugin(),
],
}
// 别忘了修改mode为production
const mode = 'production'
CSS编译器
如果需要集成其他的css编译器,需要安装对应的编译器包和翻译官:比如less、less-loader,在loader里配置less-loader即可
let rules = [
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
}
]
CSS引入的其他资源怎么办
css-loader在新版本已经自动的帮你处理好了,在之前需要url-loader和file-loader帮你做文件模块化,现在不需要了。当然这也带来个问题css-loader只是帮你打包了引用的资源,但是并未帮你模块化,如何解决?
-
file-loader出场,但是css-loader和file-loader功能冲突,会打包出两张图片,需要配置css-loader的options的url为false(具体参照css-loader的最新文档)
-
webpack5的asset资源模块(具体如何下节分析)
总结
本次代码参照 code-example / 02-example
需要注意的是,这里所有的loader都说的很简略,其实当真正用的时候才发现,每个loader都十分强大,有各种配置可以供你选择(比如less-loader可以替换解析的内容,css-loader的module有多种类型),如果遇到复杂的场景,需要我们自己去 查文档