MiniCssExtractPlugin
MiniCssExtractPlugin 插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件。这个插件需要在 webpack 5 中才能正常工作,webpack 4 中使用 extract-text-webpack-plugin 插件做 CSS 分离。之前的文章中我们介绍了 style-loader 的使用,style-loader 是将 JS 中包含的 CSS 内容以 <style> 标签的形式插入到 DOM 中,而 MiniCssExtractPlugin 插件则是将 JS 中包含的 CSS 创建一个新的文件,并且以 <link> 标签的形式插入链接到加载依赖的文件中。MiniCssExtractPlugin 作用与 style-loader 类似,但是实现方式却完全不同。MiniCssExtractPlugin 一般与 css-loader 同时使用。
注意:下面【使用】模块的案例,index.css 分离是 MiniCssExtractPlugin 做的,而通过 `<link>` 标签插入index.html 是 HtmlWebpackPlugin 插件做的,MiniCssExtractPlugin 插件可以将非入口文件通过 `<link>` 标签插入到加载依赖的文件中,即 MiniCssExtractPlugin 插入 `<link>` 仅适用于非初始(异步)块。
使用
index.js
import styles from "./index.css";
import main from "./main.css";
const divElement = document.createElement("div");
divElement.className = "demo";
divElement.innerHTML = 'mini-css-extract-plugin';
document.body.appendChild(divElement);
index.css
.demo {
color: red;
}
main.css
.demo {
font-size: 20px;
}
安装 mini-css-extract-plugin
npm install mini-css-extract-plugin -D
安装成功后,将 mini-css-extract-plugin 配置到 webpack.config.js 的 plugins 和 module 中。
webpack.config.js
...
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
...
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [
...
new MiniCssExtractPlugin()
]
}
我们在入口文件 index.js 中导入了 main.css 和 index.css 两个样式文件。一个改变字体,一个改变字体颜色。执行打包命令,可以看到在 dist 文件夹下除了 index.js 和 index.html 文件之外还生成了一个 index.css 文件。index.css 文件中包含 main.css 和 index.css 的内容。在 index.html 中通过 <link> 标签的形式引入了 index.css 文件。在浏览器中打开 dist/index.html 可以看到样式被正常展示。
上面的例子中在 index.js 中导入了两个样式文件,接下来我们试一下在入口文件 index.js 中导入 main.js 和 index.css,其中 main.js 中导入 main.css。其他配置保持不变。
index.js
import styles from "./index.css";
import { default as mainElement } from './main';
const divElement = document.createElement("div");
divElement.className = "demo";
divElement.innerHTML = 'mini-css-extract-plugin';
divElement.appendChild(mainElement);
document.body.appendChild(divElement);
main.js
import main from "./main.css";
const divElement = document.createElement("div");
divElement.className = "demo-main";
divElement.innerHTML = 'demo-main';
export default divElement;
main.css
.demo-main {
font-size: 20px;
}
执行打包命令后,dist 文件夹下依然只有 index.html,index.js,index.css 文件。查看后发现虽然在 main.js 中导入的 main.css,但由于 main.js 被 index.js 依赖。所以 css 文件内容依然都打包到了 index.css 中。
配置
MiniCssExtractPlugin 包含两部分配置,plugin 配置和 loader 配置。
Plugin Options
filename
类型:string | ((pathData: PathData, assetInfo?: AssetInfo) => string);
默认值:[name].css
作用:输出的 css 文件的名称,默认为 chunkName 值。
webpack.config.js
module.exports = {
plugins: [
new MiniCssExtractPlugin({
...
filename: '[name].css' // index.css
// filename: (pathData) => {
// return pathData.hash + '-index.css';
// }, // 8de455759e47e7f4d53b-index.css
}),
]
};
chunkFilename
类型:string | ((pathData: PathData, assetInfo?: AssetInfo) => string);
默认值:基于 filename
作用:修改非入口文件的打包后的名称。
index.js
import styles from "./index.css";
// 将 main.js 打包到单独文件
const mainElement = import(/* webpackChunkName: "main" */ './main');
...
webpack.config.js
module.exports = {
plugins: [
new MiniCssExtractPlugin({
chunkFilename: 'chunk-[id].css', // chunk-main.css
}),
]
};
打开 dist 我们可以看到 main.js 文件已经单独打包,并且生成了一个 chunk-name.css 文件。
ignoreOrder
类型:boolean
默认值:false
作用:模块中加载 css 文件顺序不一致是否发出警告,例如:1.js 中加载 css 的顺序是 a.css、b.css,2.js 中加载顺序是 b.css、a.css,就会发出警告,详细可看下官网 issue
webpack.config.js
module.exports = {
...
plugins: [
new MiniCssExtractPlugin({
ignoreOrder: false,
})
]
};
insert
类型:string | ((linkTag: HTMLLinkElement) => void)
默认值:document.head.appendChild(linkTag),即默认插入到 DOM 文件的 head 中
作用:打包的 CSS 文件,通过 <link> 标签插入的位置。
index.js
import styles from "./index.css";
const divElement = document.createElement("div");
// import 方法导入的模块为异步加载
import(/* webpackChunkName: "main" */ './main').then(res => {
divElement.appendChild(res.default)
});
divElement.className = "demo";
divElement.innerHTML = 'mini-css-extract-plugin';
document.body.appendChild(divElement);
index.html
...
<body>
<div id="div-element"></div>
</body>
webpack.config.js
module.exports = {
...
plugins: [
new MiniCssExtractPlugin({
insert: '#div-element'
})
]
};
执行打包命令后,在 dist/index.html 文件中,只包含了 index.css 的 <link> 标签,在浏览器中运行 index.html,在控制台可以看到 chunk-main.css 的 <link> 标签被插入到选择器为 #div-element 元素的后面。在生成的 index.js 文件中可以看到创建 link 标签的源码。
attributes
类型:object
默认值:{}
作用:在 <link>
标签中添加属性
webpack.config.js
module.exports = {
...
plugins: [
...
new MiniCssExtractPlugin({
attributes: {
"data-target": "data" // <link data-target="data" rel="stylesheet" type="text/css" href=".../dist/main.css">
},
})
]
};
linkType
类型:string | boolean
默认值:text/css
作用:修改 <link>
标签中 type 属性,type 的默认值为 text/css。
webpack.config.js
module.exports = {
...
plugins: [
...
new MiniCssExtractPlugin({
linkType: "text/css" // <link type="text/css" ...>
// linkType: false // <link rel="stylesheet" href=".../dist/main.css">
})
]
};
runtime
类型:boolean
默认值:true
作用:允许启用/禁用运行时生成。
webpack.config.js
module.exports = {
...
plugins: [
...
new MiniCssExtractPlugin({
runtime: false // 运行 index.html 时,main.css 不会被插入到 DOM 中。
})
]
};
Loader Options
publicPath
类型:string | ((resourcePath: string, rootContext: string) => string)
默认值:webpackOptions.output 选项的值
作用:输出的 CSS 文件中,为图像、文件等外部资源指定自定义公共路径。
main.css
.demo-main {
font-size: 20px;
background: url(./img/1.png);
}
webpack.config.js
module.exports = {
...
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "/public/path/to/", // main.css background: url(/public/path/to/e30cb9c395cbb5ae00e9.png);
},
}, "css-loader"],
},
],
},
};
打包成功后,查看生成的 main.css 文件,background 地址已经被替换成传入的 publicPath,通过传入 publicPath 可以引用外部资源。
emit
类型:boolean
默认值:true
作用:提取的 CSS 是否生成对应文件。当 emit 值为 true 会生成 CSS 文件,值为 false 不生成 CSS 文件。
webpack.config.js
module.exports = {
...
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
emit: false, // 打包后的 dist 中没有生成 index.css 和 main.css,运行 index.html 样式不生效
},
}, "css-loader"],
},
],
},
};
esModule
类型:boolean
默认值:true
作用:生成的文件是否使用 ES 模块语法,开启 ES 语法对 tree-shaking 将非常有用。
webpack.config.js
module.exports = {
...
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: false, // 启用CommonJS 语法
},
}, "css-loader"],
},
],
},
};
总结
此章节演示了 MiniCssExtractPlugin 的用法和包含的配置参数。MiniCssExtractPlugin 还有一些推荐的例子,感兴趣的同学可查看官方。
WebpackManifestPlugin
WebpackManifestPlugin 是一个 webpack 插件,此插件的作用是生成资产清单即 manifest.json 文件,在使用此插件前,我们先看下什么是 manifest 以及 manifest 的作用,以下引自 webpack 官网。
一旦你的应用在浏览器中以 index.html 文件的形式被打开,一些 bundle 和应用需要的各种资源都需要用某种方式被加载与链接起来。在经过打包、压缩、>为延迟加载而拆分为细小的 chunk 这些 webpack 优化 之后,你精心安排的 /src 目录的文件结构都已经不再存在。所以 webpack 如何管理所有所需模 >块之间的交互呢?这就是 manifest 数据用途的由来……
总结来说,manifest.json 就是记录项目中生成的 bundle 之间的映射关系。有了这份清单,我们可以通过特定的方法加载资源,如服务端渲染或通过遍历 manifest.json 将记录输出到页面上等。在当前流行的微前端框架中,通过引入不同子项目的 manifest.json 文件,并遍历文件内容动态输出到 DOM 中,从而实现加载不同子项目工程,这会比手动获取子项目资源清单减少出错概率和省事的多。
使用
index.js
import styles from "./index.css";
const divElement = document.createElement("div");
divElement.className = "demo";
divElement.innerHTML = 'webpack-manifest-plugin';
document.body.appendChild(divElement);
index.css
.demo {
color: red;
background: url(./img/1.png);
}
安装 webpack-manifest-plugin
npm install webpack-manifest-plugin -D
安装成功后,将 webpack-manifest-plugin 配置到 webpack.config.js 的 plugins 中。
webpack.config.js
...
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
module.exports = {
...
plugins: [
...
new WebpackManifestPlugin({
publicPath: './'
})
]
}
我们在 index.js 文件中创建了一个 div 标签,在 index.css 中设置了 div 标签的字体颜色和背景图片,此时执行打包命令,打包成功后在 dist 中可以看到除了项目资源文件外还有一个 manifest.json 文件。打开 manifest.json 文件看下内容。
manifest.json 包含了资源的映射关系,我们需要遍历 manifest.json 对象的内容,将需要的如 js 资源通过 createElement 等方式挂载到 index.html 中项目即可正常使用。
配置
以下为包含部分常用配置,全部配置可查看官网
basePath
类型:String
默认值:''
作用:生成的 manifest.json 文件中,basePath 参数传入的值将添加到对象的 key 值前面。
webpack.config.js
module.exports = {
plugins: [
new WebpackManifestPlugin({
...
basePath: 'src' // "src/index.js": ".../index.js",
basePath: '' // "index.js": ".../index.js",
}),
]
};
fileName
类型:String
默认值:manifest.json
作用:fileName 传入的值作为输出的文件清单的名称。
webpack.config.js
module.exports = {
plugins: [
new WebpackManifestPlugin({
fileName: 'manifest-filename.json' // manifest.json -> manifest-filename.json
})
]
};
filter
类型:(file: FileDescriptor) => Boolean
默认值:undefined
作用:执行 filter 回调函数,返回 true 则 manifest.json 中包含 bundle 的映射关系,返回 false 则不包含此 bundle 映射关系。
webpack.config.js
module.exports = {
...
plugins: [
new WebpackManifestPlugin({
filter: (file) => {
return file?.name?.endsWith('.js') // manifest.json 中只包含 js 拓展名的文件
}
})
]
};
generate
类型:(seed: Object, files: FileDescriptor[], entries: string[]) => Object
默认值:undefined
作用:自定义修改生成的 manifest.json 中的键值对内容,generate 传入的函数返回值需要为对象。
webpack.config.js
module.exports = {
...
plugins: [
new WebpackManifestPlugin({
generate: (seed, files, entries) => {
console.log(seed, 'seed')
console.log(files, 'files')
console.log(entries, 'entries')
return { 'main-index': 'index.js' }
}
}) // manifest.json 中内容 { "main-index": "index.js" }
]
};
map
类型:(file: FileDescriptor) => FileDescriptor
默认值:undefined
作用:自定义修改生成的 manifest.json 中的键值对内容。
webpack.config.js
module.exports = {
...
plugins: [
...
new WebpackManifestPlugin({
map: (file) => {
const fileName = file?.name;
if (file?.name?.endsWith('.js')) {
file.name = 'assets.' + fileName
}
return file
}
})
// { "assets.main.js": "auto/main.js" ... }
]
};
publicPath
类型:String
默认值:webpack.config.js 中的 output.publicPath 值
作用:publicPath 传入的内容将添加到 manifest.json 对象的值前面。
webpack.config.js
module.exports = {
...
plugins: [
...
new WebpackManifestPlugin({
// {
// "index.js": "./dist-public/index.js",
// "1.png": "./dist-public/2b2001bb98465dd14a87.png",
// "index.html": "./dist-public/index.html"
// }
publicPath: './dist-public'
})
]
};
serialize
类型:(Object) => string
默认值:undefined
作用:格式化 manifest.json 中的内容。
webpack.config.js
module.exports = {
...
plugins: [
...
new WebpackManifestPlugin({
serialize: (obj) => {
console.log(obj)
return JSON.stringify(obj) // {"index.js":"auto/index.js","1.png":"auto/2b2001bb98465dd14a87.png","index.html":"auto/index.html"}
}
})
]
};
总结
此章节演示了 WebpackManifestPlugin 的用法和包含的部分常用配置参数,通过 WebpackManifestPlugin 生成的资源清单可以让我们在项目中快速找到引用的依赖文件路径,这对于服务端渲染或微前端等将非常有用。
阅读量:1135
点赞量:0
收藏量:0