一、定义
在 Webpack 中,Plugin(插件) 是用来扩展 Webpack 功能的 JavaScript 模块,它可以在 Webpack 构建流程的不同生命周期(钩子/Hooks)中执行自定义任务。
(1)Plugin 的本质
- Plugin 是一个 JavaScript 类(或构造函数),必须实现
apply(compiler)方法。 - Webpack 在运行时会自动调用
apply方法,并传入compiler对象,让插件可以访问 Webpack 的构建流程。 - 插件可以监听 Webpack 的生命周期钩子(Hooks) ,并在特定时机执行自定义逻辑(如修改输出、优化资源、生成额外文件等)。
(2)Plugin 的核心作用
- 优化构建流程(如压缩代码、拆分代码、Tree Shaking)
- 资源管理(如自动生成 HTML、拷贝静态文件、提取 CSS)
- 增强功能(如热更新 HMR、分析打包体积、注入环境变量)
- 自定义构建行为(如修改打包后的文件、生成 manifest 文件)
二、常见有哪些plugin
-
基础 Plugin:
HtmlWebpackPlugin:自动生成 HTML 文件,并自动注入打包后的 bundleCleanWebpackPlugin:在每次构建前清理输出目录DefinePlugin:定义编译时可用的全局常量
-
优化类 Plugin:
MiniCssExtractPlugin:将 CSS 提取到单独的文件中CompressionWebpackPlugin:生成 gzip 压缩的资源文件TerserWebpackPlugin:JavaScript 代码压缩优化
-
开发辅助 Plugin:
HotModuleReplacementPlugin:启用热模块替换(HMR)BundleAnalyzerPlugin:可视化分析打包文件大小ForkTsCheckerWebpackPlugin:在单独进程中进行 TypeScript 类型检查
-
高级功能 Plugin:
DllPlugin和DllReferencePlugin:用于实现动态链接库,提升构建速度ModuleFederationPlugin:实现微前端架构的模块联邦CopyWebpackPlugin:复制文件或目录到构建目录
重点介绍一下DllPlugin 和DllReferencePlugin
- 背景: 在大型项目中,我们通常有很多第三方库(如react, lodash等),这些库的代码一般不会频繁改动。但是,每次构建时Webpack都要重新解析和构建这些代码,导致构建速度变慢。DllPlugin和DllReferencePlugin就是为了解决这个问题而设计的。它们通过预编译第三方库,将其打包成一个动态链接库(DLL),然后在项目构建时直接引用这个预编译好的库,从而避免重复构建。
- DllPlugin:作用:用于打包第三方库,生成一个动态链接库(DLL)文件,同时还会生成一个manifest.json文件(描述哪些库被打包进了DLL)。配置位置:通常在一个单独的webpack配置文件中使用(比如webpack.dll.config.js),然后通过运行这个配置文件来生成DLL文件。配置示例(webpack.dll.config.js):
const webpack = require('webpack');
const path = require('path');
module.exports = {
entry: {vendor: ['react', 'react-dom', 'lodash'] // 指定要打包的第三方库},
output: {
path: path.join(__dirname, 'dll'),
filename: '[name].dll.js',library: '[name]_dll' // 暴露出的全局变量名
},
plugins: [
new webpack.DllPlugin({path: path.join(__dirname, 'dll', '[name]-manifest.json'), // manifest.json文件的输出路径name: '[name]_dll' // 必须与output.library保持一致})
]};
运行这个配置后,会在dll目录下生成vendor.dll.js和vendor-manifest.json。、
- DllReferencePlugin:作用:在项目构建的配置中引用DllPlugin生成的manifest.json文件,告诉Webpack哪些库不需要打包,而是从DLL中引用。配置位置:在项目的主webpack配置文件中使用(比如webpack.config.js)。配置示例(webpack.config.js):
module.exports = {// ...其他配置
plugins: [
new webpack.DllReferencePlugin({manifest: path.join(__dirname, 'dll', 'vendor-manifest.json')})]};
- 使用步骤:a. 创建一个单独的webpack配置文件(如webpack.dll.config.js)用于打包DLL,并运行它(例如:webpack --config webpack.dll.config.js)。b. 在主配置文件中(webpack.config.js)使用DllReferencePlugin引用生成的manifest文件。c. 在HTML中手动引入生成的DLL文件(vendor.dll.js),或者使用add-asset-html-webpack-plugin插件自动引入。
- 注意事项:- 当DLL中的库需要更新时,需要重新运行DLL的构建。- 如果修改了DLL配置中的entry,需要重新生成DLL,否则可能会引用不到。- 在开发环境和生产环境都可以使用,但通常用于开发环境以提升构建速度。
- 在Webpack 5中的情况:Webpack 5已经内置了更强大的缓存机制,并且推荐使用“hard-source-webpack-plugin”或者Webpack 5自带的持久性缓存(cache: { type: 'filesystem' })来提升构建性能。因此,在Webpack 5中,DLLPlugin的使用已经减少。但是,对于特别大型的项目,如果缓存还不能满足性能要求,依然可以使用DLLPlugin。
- 总结:DllPlugin和DllReferencePlugin通过分离第三方库来提升构建速度,但需要额外的配置步骤。在Webpack 5中,可以考虑使用新的缓存机制来替代。
// webpack.config.js
module.exports = {
cache: {
type: 'filesystem', // 启用持久化缓存
buildDependencies: {
config: [__filename] // 配置文件变更时自动失效缓存
}
},
// 替代 DLL 的优化配置
optimization: {
moduleIds: 'deterministic',
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors'
}
}
}
}
}
三、如何自定义plugin
// 自定义插件示例:在构建完成后输出提示信息
class MyWebpackPlugin {
// 可接收配置参数
constructor(options) {
this.options = options || {};
}
// apply 方法会被 webpack compiler 调用
apply(compiler) {
// 注册钩子函数
compiler.hooks.done.tap('MyWebpackPlugin', (stats) => {
console.log('构建已完成!');
if (this.options.message) {
console.log(this.options.message);
}
});
// 更多钩子示例:在emit阶段(生成资源到output目录之前)执行
compiler.hooks.emit.tapAsync('MyWebpackPlugin', (compilation, callback) => {
// compilation 对象包含当前构建的所有信息
console.log('准备生成资源文件...');
// 可以修改compilation.assets来添加或修改资源
callback();
});
}
}
// 使用方式
module.exports = {
// ...其他配置
plugins: [
new MyWebpackPlugin({
message: '这是我的自定义插件!'
})
]
};