【Webpack】🔥Webpack 插件开发如此简单!
本文使用的Webpack-Quickly-Starter快速搭建 Webpack4 本地学习环境。
建议多阅读 Webpack 文档《Writing a Plugin》章节,学习开发简单插件。
本文将带你一起开发你的第一个 Webpack 插件,从 Webpack 配置工程师,迈向 Webpack 开发工程师!
做自己的轮子,让别人用去吧。
完整代码存放在:https://github.com/pingan8787/script-timestamp-webpack-plugin
一、背景介绍
本文灵感源自业务中的经验总结,不怕神一样的产品,只怕一根筋的开发。
在项目打包遇到问题:“当项目托管到 CDN 平台,希望实现项目中的 index.js 不被缓存”。因为我们需要修改 index.js
中的内容,不想用户被缓存。
思考一阵,有这么几种思路:
- 在 CDN 平台中过滤该文件的缓存设置;
- 查找 DOM 元素,修改该
script
标签的src
值,并添加时时间戳; - 打包时动态创建
script
标签引入文件,并添加时时间戳。
(聪明的你还有其他方法,欢迎讨论)
思路分析:
- 显然修改 CDN 设置的话,治标不治本;
- 在模版文件中,添加
script
标签,执行获取 Webpack 自动添加的script
标签并为其src
值添加时间戳。但事实是还没等你修改完, js 文件已经加载完毕,所以放弃 - 需要在
index.html
生成之前,修改 js 文件的路径,并添加时间戳。
于是我准备使用第三种方式,在 index.html
生成之前完成下面修改:
问题简单,实际还是想试试开发 Webpack Plugin。
二、基础知识
Webpack 使用阶段式的构建回调,开发者可以引入它们自己的行为到 Webpack 构建流程中。
在开发之前,需要了解以下 Webpack 相关概念:
2.1 Webpack 插件组成
在自定义插件之前,我们需要了解,一个 Webpack 插件由哪些构成,下面摘抄文档:
- 一个具名 JavaScript 函数;
- 在它的原型上定义 apply 方法;
- 指定一个触及到 Webpack 本身的事件钩子;
- 操作 Webpack 内部的实例特定数据;
- 在实现功能后调用 Webpack 提供的 callback。
2.2 Webpack 插件基本架构
插件由一个构造函数实例化出来。构造函数定义 apply
方法,在安装插件时,apply
方法会被 Webpack compiler
调用一次。apply
方法可以接收一个 Webpack compiler
对象的引用,从而可以在回调函数中访问到 compiler
对象。
官方文档提供一个简单的插件结构:
class HelloWorldPlugin {
apply(compiler) {
compiler.hooks.done.tap('Hello World Plugin', (
stats /* 在 hook 被触及时,会将 stats 作为参数传入。 */
) => {
console.log('Hello World!');
});
}
}
module.exports = HelloWorldPlugin;
使用插件:
// webpack.config.js
var HelloWorldPlugin = require('hello-world');
module.exports = {
// ... 这里是其他配置 ...
plugins: [new HelloWorldPlugin({
options: true })]
};
2.3 HtmlWebpackPlugin 介绍
HtmlWebpackPlugin 简化了 HTML 文件的创建,以便为你的 Webpack 包提供服务。这对于在文件名中包含每次会随着编译而发生变化哈希的 webp