『Webpack系列』—— MiniCssExtractPlugin插件用法详解
一、插件的作用
This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.
用某度翻译后:“该插件将CSS提取到单独的文件中。它为每个包含CSS的JS文件创建一个CSS文件。它支持CSS和SourceMap的按需加载。”
包含CSS的JS文件,JS文件不是指组件对应的JS文件,是指打包后生成的JS文件。
二、插件的优点
在Webpack4.0之前,是用ExtractTextWebpackPlugin插件来提取css的,与其相比有如下优点
- 异步加载
- 没有重复的编译(性能)
- 更容易使用
- 特定于CSS
三、插件的简单用法
搭建个简单的Wenpack Demo,演示一下。
先安装MiniCssExtractPlugin插件。
npm install --save-dev mini-css-extract-plugin
安装成功后,在webpack.config.js文件中配置。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: {
main: "./src/main.js",
},
plugins:[
new MiniCssExtractPlugin(),
],
module:{
rules:[
{
test: /\.css$/,
use:[MiniCssExtractPlugin.loader,'css-loader']
},
]
}
}
入口文件为main.js
import './css/main.css'
import './index'
console.log('main')
index.js
import './css/index.css'
import './index'
console.log('main')
main.css和index.css内容一样
.class{
color:red
}
执行命令webpack
,可以在dist文件夹中看到打包生成的三个文件
项目中有两个包含CSS的JS文件,但是只打包生成了一个CSS文件,证实了上面 “它为每个包含CSS的JS文件创建一个CSS文件”中的包含CSS的JS文件是指打包后生成的JS文件。
在浏览器打开index.html,在开发者工具中可以看到如下图所示
打包生成的CSS文件用link
标签引入
如果没有用MiniCssExtractPlugin插件呢,改一下webpack.config.js文件中配置。
module:{
rules:[
{
test: /\.css$/,
use:['style-loader','css-loader']
},
]
}
再执行webpack
命令。在浏览器打开index.html,会发现样式在头部用<style></style>
嵌入式引入。
看到这里也应该明白了MiniCssExtractPlugin插件的作用,就是提取JS中的CSS样式,用link
外部引入,减少JS文件的大小,简称CCSS样式分离。
MiniCssExtractPlugin插件不能和style-loader共用
四、插件的参数
filename
控制从打包后的入口JS文件中提取CSS样式生成的CSS文件的名称。
module.exports = {
entry: {
main: "./src/main.js",
},
plugins:[
new MiniCssExtractPlugin({
filename: '[name]-test.css',
}),
]
}
执行webpack
命令,可以在dist文件夹中看到打包生成的CSS文件名称为main-test.css
chunkFilename
控制从打包后的非入口JS文件中提取CSS样式生成的CSS文件的名称。
module.exports = {
entry: {
main: "./src/main.js",
},
plugins:[
new MiniCssExtractPlugin({
filename: '[name]-test.css',
chunkFilename: '[name]-test.css'
}),
]
}
main.js
import './css/main.css'
import(/*webpackChunkName: "index"*/ './index')
console.log('main')
执行webpack
命令,可以在dist文件夹中看到非入口JS文件index.bundle.js提取出来的CSS文件名为index-test.css。
moduleFilename
该参数的值是个函数,主要应用多入口场景,控制从打包后的入口JS文件中提取CSS样式生成的CSS文件的名称。
如果和filename
参数共用,filename
将不起作用。
module.exports = {
entry: {
main: "./src/main.js",
main1: "./src/main1.js",
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].css',
moduleFilename: (
{ name }) => {
return `${name}.css`
},
}),
],
}
执行webpack
命令,打包生成的文件如下图所示
ignoreOrder
控制css的引入顺序不一致是否警告,true
表示警告,false
表示不警告。
简单的说,就是在js里css的引入顺序导致的问题,多个css的在js里的引入顺序不同,就会有这个警告。例如,在1.js 里,引入的顺序是a.css, b.css; 在2.js里,引入顺序是b.css,a.css,出现了这种引入顺序不同,就导致了警告。在两个js里把引入顺序调成一致,就没问题了。在1.js和2.js里的引入顺序都调整成a.css, b.css 就没有那个警告了。
当然也可以设置ignoreOrder
参数为false
,关闭这些警告。
五、插件loader的参数
publicPath
默认值是webpackOptions.output,如下面所示,默认值就是path.resolve(__dirname, 'dist')
。
module.exports = {
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, 'dist'),
},
}
作用是指定目标文件的定制公共路径。有点难理解,下面用一个实例来解释。
main.css
body{
background: url('./LOGO.png');
}
main.js入口文件
import './css/main.css'
console.log('main')
因为main.css中引入图片,要用file-loader处理一下。在webpack.config.js中这么配置
module.exports = {
module: {
rules: [
{
test: /\.png$/,
use: [
{
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
]
},
],
},
};
执行webpack
命令,打包生成的CSS文件如下main.css如下所示
图片放在dist文件夹下img文件夹中,这时在浏览器打开index.html,图片是可以加载出来。
如果改一下生成的CSS文件路径。
module.exports = {
plugins:[
new MiniCssExtractPlugin({
filename: 'css/[name].css',
}),
]
}
再执行webpack
命令,打包生成的CSS文件如下main.css如下所示
图片还是放在dist文件夹下img文件夹中,但是在浏览器打开index.html,图片无法加载出来。
因为main.css 中图片的引用路径是img/LOGO.af6d901d.png
,显然路径不对,所以图片无法加载出来,要把图片的引用路径改成../img/LOGO.af6d901d.png
才可以加载出来。
但是不可能去修改打包生成的文件,那要如何解决这个错误呢?此时publicPath参数的作用就体现出来了,可以利用publicPath参数来修改图片的引用路径,修改一下webpack.config.js的配置。
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader:MiniCssExtractPlugin.loader,
options:{
publicPath:'../'
}
},
'css-loader']
},
],
}
}
再执行webpack
命令,打包生成的CSS文件如下main.css如下所示
在浏览器打开index.html,图片可以加载出来。
publicPath的作用指定目标文件的定制公共路径,可以理解为指定../img/LOGO.af6d901d.png
中img
前面的路径../
。
esModule
默认值为false
,代表MiniCssExtractPlugin生成使用CommonJS模块语法的JS模块。
若为true
,代表MiniCssExtractPlugin生成使用ES6模块语法的JS模块。
hmr
默认为false
,为true
时启动样式文件热更新。
在不启用样式文件热更新时,修改CSS源文件的时候,修改的样式不会自动在页面上显示,需要手动刷新页面,才会加载变化。启动样式文件热更新后,不再需要刷新整个页面,修改的样式就可以自动在页面上显示。
上面说到过MiniCssExtractPlugin插件不能和style-loader共用,一般在开发环境中配置style-loader,在生产环境中配置MiniCssExtractPlugin插件。其实style-loader也可以实现样式文件热更新。
HMR is an opt-in feature that only affects modules containing HMR code. One example would be patching styling through the style-loader. In order for patching to work, the style-loader implements the HMR interface; when it receives an update through HMR, it replaces the old styles with the new ones.
但是MiniCssExtractPlugin插件的样式文件热更新比style-loader更强大一些。比如说在public文件夹中的index.html引入一个CSS样式文件,如果修改了这个CSS样式文件的源码,使用style-loader是不会触发样式文件热更新,因为style-loader只热更新JS中引入的样式,但MiniCssExtractPlugin插件会热更新加载所有的样式。
一般只在生产环境中将hmr
设置为true
。
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader:MiniCssExtractPlugin.loader,
options:{
publicPath:'../',
hmr: process.env.NODE_ENV === 'development',
}
},
'css-loader']
},
],
}
}
reloadAll
if hmr does not work, this is a forceful method.
一般配合hrm
参数使用,为true
时,表示样式文件热更新不起作用时重新加载全部样式。
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader:MiniCssExtractPlugin.loader,
options:{
publicPath:'../',
hmr: process.env.NODE_ENV === 'development',
reloadAll: true
}
},
'css-loader']
},
],
}
}
六、将所有CSS提取到一个文件中
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true,
},
},
},
},
}
执行webpack
命令,打包生成的文件如下如下所示
转载自:https://juejin.cn/post/6850418117500715015