css-loader
经过 css-loader 处理后,CSS 代码会被转译为等价 JS 字符串,但这些字符串还不会对页面样式产生影响,需要继续接入 style-loader 加载器。
css-loader 只是解决打包报错 但是不会把 css 引入到 html 中
module.exports = {
module: {
rules: [
{
test: /.css$/i,
use: ["css-loader"],
},
],
},
};
style-loader
style-loader 并不会对代码内容做任何修改,而是简单注入一系列运行时代码,用于将 css-loader 转译出的 JS 字符串插入到页面的 style 标签。
PS:注意保持 style-loader 在前,css-loader 在后
module.exports = {
module: {
rules: [
{
test: /.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
经过 style-loader + css-loader 处理后,样式代码最终会被写入 Bundle 文件,并在运行时通过 style 标签注入到页面。这种将 JS、CSS 代码合并进同一个产物文件的方式有几个问题:
- JS、CSS 资源无法并行加载,从而降低页面性能;
- 资源缓存粒度变大,JS、CSS 任意一种变更都会致使缓存失效。
mini-css-extract-plugin
生产环境中通常会用 mini-css-extract-plugin 插件替代 style-loader,将样式代码抽离成单独的 CSS 文件。
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
module.exports = {
module: {
rules: [{
test: /.css$/,
use: [
// 根据运行环境判断使用那个 loader
(process.env.NODE_ENV === 'development' ?
'style-loader' :
MiniCssExtractPlugin.loader),
'css-loader'
]
}]
},
plugins: [
new MiniCssExtractPlugin(),
new HTMLWebpackPlugin()
]
}
这里需要注意几个点:
- mini-css-extract-plugin 库同时提供 Loader、Plugin 组件,需要同时使用
- mini-css-extract-plugin 不能与 style-loader 混用,否则报错,所以上述示例中第 9 行需要判断 process.env.NODE_ENV 环境变量决定使用那个 Loader
- mini-css-extract-plugin 需要与 html-webpack-plugin 同时使用,才能将产物路径以 link 标签方式插入到 html 中
综上,在 Webpack 中处理 CSS,通常需要使用 css-loader + style-loader 或 css-loader + mini-css-extract-plugin 组合,两种方式最终都能实现加载样式代码的效果。但鉴于原生 CSS 语言的种种缺陷,我们还可以在此基础上增加更多 Webpack 组件,更优雅、高效地编写页面样式
三者的区别
| css-loader | 处理 css 文件 |
|---|---|
| style-loader | 把 js 中 import 导入的样式文件代码,打包到 js 文件中,运行 js 文件时,将样式自动插入到<style>标签中 |
| mini-css-extract-plugin | 把 js 中 import 导入的样式文件代码,打包成一个实际的 css 文件,结合 html-webpack-plugin,在 dist/index.html 中以 link 插入 css 文件;默认将 js 中 import 的多个 css 文件,打包时合成一个 |
三种组件各司其职:css-loader 让 Webpack 能够正确理解 CSS 代码、分析资源依赖;style-loader、mini-css-extract-plugin 则通过适当方式将 CSS 插入到页面,对页面样式产生影响: