大家有没有遇到过这些问题:
- webpack 打包之后的文件没有压缩
- 静态文件要手动拷贝到输出目录
- 代码中写了很多环境判断的多余代码
上一篇 「webpack 核心特性」loader 说到 webpack 的 loader
机制,本文主要聊一聊另外一个核心特性:插件(plugin
)。
插件机制就是为了完成项目中除了资源模块打包以外的其他自动化工作,解决上述的问题。
plugin
是用来扩展 webpack 功能的,通过在构建流程里注入钩子实现,它为 webpack 带来了很大的灵活性。
plugin 相对于 loader 有哪些区别?
loader
是转换器,将一种文件编译转换为另一个文件,操作的是文件。例如:将 .less
文件转换成 .css
文件。
plugin
是扩展器,它是针对 loader
结束之后,打包的整个过程。它并不直接操作文件,而是基于事件机制工作。在 webpack 构建流程中的特定时机会广播对应的事件,插件可以监听这些事件的发生,在特定的时机做对应的事情。包括:打包优化,资源管理,注入环境变量。
plugin 该怎么配置呢?
例如 HtmlWebpackPlugin
可以为我们生成一个 HTML 文件,其中包括使用 script
标签的 body 中的所有模块。看下如何配置:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpackConfig = {
...
plugins: [new HtmlWebpackPlugin()]
};
温馨提示:
loader
在 module.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个对象,内部包含了 test(类型文件)、loader、options(参数)等属性。plugin
则单独配置,类型为数组,每一项是一个plugin
的实例,参数都通过构造函数传入。
有哪些常见的 plugin?
下面整理的插件列表来自 webpack 中文官网,大家看见不熟悉的 plugin
可以点击名称跳转,看一看,了解一下具体玩法。
名称 | 描述 |
---|---|
AggressiveSplittingPlugin | 将原来的 chunk 分成更小的 chunk |
BabelMinifyWebpackPlugin | 使用 babel-minify进行压缩 |
BannerPlugin | 在每个生成的 chunk 顶部添加 banner |
CommonsChunkPlugin | 提取 chunks 之间共享的通用模块 |
CompressionWebpackPlugin | 预先准备的资源压缩版本,使用 Content-Encoding 提供访问服务 |
ContextReplacementPlugin | 重写 require 表达式的推断上下文 |
CopyWebpackPlugin | 将单个文件或整个目录复制到构建目录 |
DefinePlugin | 允许在编译时(compile time)配置的全局常量 |
DllPlugin | 为了极大减少构建时间,进行 dll 分包 |
EnvironmentPlugin | DefinePlugin 中 process.env 键的简写方式。 |
ExtractTextWebpackPlugin | 从 bundle 中提取文本(CSS)到单独的文件 |
HotModuleReplacementPlugin | 启用模块热替换(Enable Hot Module Replacement - HMR) |
HtmlWebpackPlugin | 简单创建 HTML 文件,用于服务器访问 |
I18nWebpackPlugin | 为 bundle 增加国际化支持 |
IgnorePlugin | 从 bundle 中排除某些模块 |
LimitChunkCountPlugin | 设置 chunk 的最小/最大限制,以微调和控制 chunk |
LoaderOptionsPlugin | 用于从 webpack 1 迁移到 webpack 2 |
MinChunkSizePlugin | 确保 chunk 大小超过指定限制 |
NoEmitOnErrorsPlugin | 在输出阶段时,遇到编译错误跳过 |
NormalModuleReplacementPlugin | 替换与正则表达式匹配的资源 |
NpmInstallWebpackPlugin | 在开发时自动安装缺少的依赖 |
ProvidePlugin | 不必通过 import/require 使用模块 |
SourceMapDevToolPlugin | 对 source map 进行更细粒度的控制 |
EvalSourceMapDevToolPlugin | 对 eval source map 进行更细粒度的控制 |
UglifyjsWebpackPlugin | 可以控制项目中 UglifyJS 的版本 |
ZopfliWebpackPlugin | 通过 node-zopfli 将资源预先压缩的版本 |
怎么写一个 plugin?
在说怎么写插件之前,先简单介绍几个好玩的东西:tapable
、compiler
和 compilation
。
tapable
tapable
是一个类似于 nodejs
的 EventEmitter
的库, 主要是控制钩子函数的发布与订阅。当然,tapable
提供的 hook
机制比较全面,分为同步和异步两个大类(异步中又区分异步并行和异步串行),而根据事件执行的终止条件的不同,由衍生出 Bail
/ Waterfall
/ Loop
类型。
基本使用:
const {
SyncHook