来写一个 Webpack 构建信息插件
- 使用过
Webpack
插件 - 阅读过该章节 Webpack plugin
tips: 别指望我这一篇文章能够把 plugin
讲清楚,更多我的希望能做到抛砖引玉的效果。
目标
我们的目标很明确:造一个插件在构建完成后,开发者能够知道一些构建信息,如果构建失败了有失败原因,能够通知开发者及时处理。
目标很明确,剩下的问题就是怎么达成目标。
在查资料的时候偶然看到这篇文章:
webpack 源码阅读一:webpack 流程以及重要钩子
阅读后发现 done
钩子,也许能够在这个钩子做点文章……
开发插件
使用 vue-cli
初始化 vue2
的项目。
并在根目录创建 build-info.js
const pluginName = "BuildInfoPlugin";
class BuildInfoPlugin {
apply(compiler) {
compiler.hooks.done.tap(pluginName, (stats) => {
console.log("webpack 构建的结果:", stats);
});
}
}
module.exports = BuildInfoPlugin;
修改 vue.config.js
const { defineConfig } = require("@vue/cli-service");
const BuildInfoPlugin = require("./build-info");
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
plugins: [new BuildInfoPlugin()],
},
});
执行 npm run build
打印的有点多哇。我拉个晓得拉个是我的用到的……
调试
根目录创建 .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "调试 webpack 插件",
"skipFiles": ["<node_internals>/**"],
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "build"]
}
]
}
再修改下 build-info.js
const pluginName = "BuildInfoPlugin";
class BuildInfoPlugin {
apply(compiler) {
compiler.hooks.done.tap(pluginName, (stats) => {
console.log("webpack 构建的结果:", stats);
// eslint-disable-next-line no-debugger
debugger;
});
}
}
module.exports = BuildInfoPlugin;
当你点击红框的按钮时,就开始进入调试流程。
代码会在我们打 debugger
的地方暂停运行……还可以在左侧看到一堆信息(不知道怎么描述了)
那 stats
是哈玩意就一清二楚了……
写入构建日志
改造下 build-info.js
const fs = require("fs");
const pluginName = "BuildInfoPlugin";
class BuildInfoPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.done.tap(pluginName, (stats) => {
const {
compilation: { errors, startTime, endTime, outputOptions },
} = stats;
// 如果构建没有错误
if (!errors.length) {
const appName = this.options.appName;
let log = `console.log("------${appName}构建日志------")
console.log("开始时间:", ${startTime})
console.log("结束时间:", ${endTime})
`;
// 从 outputOptions 中拿到构建输出的目录
const filePath = `${outputOptions.path}/index.html`;
let content = fs.readFileSync(filePath, "utf-8");
const scriptPos = content.indexOf("</body>");
content = `${content.slice(
0,
scriptPos
)}<script>${log}</script>${content.slice(scriptPos)}`;
// 最后写入日志
fs.writeFileSync(filePath, content, "utf-8");
}
});
}
}
module.exports = BuildInfoPlugin;
vue.config.js
也要改造下!
// 可以在这里增加各种信息,如 `last commit`, 自研包版本, 构建人信息等等……
plugins: [
new BuildInfoPlugin({
appName: "hello-world", // 增加 appName
}),
],
执行构建后,使用 live service
启动项目,即可查看到构建日志信息。
构建失败
上面的代码,我们只考虑了构建成功场景,如果构建失败的话怎么处理呢?
一般情况下,是不用管…… cicd
工具已经很成熟了,构建失败或者成功可以通过 cicd
钩子接入不同的消息机器人。
当然我们要在插件里做 构建失败
的通知也是很简单的!
const fs = require("fs");
const axios = require("axios");
const pluginName = "BuildInfoPlugin";
class BuildInfoPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.done.tapAsync(pluginName, async (stats, callback) => {
const appName = this.options.appName;
const {
compilation: { errors, startTime, endTime, outputOptions },
} = stats;
// 如果构建没有错误;
if (!errors.length) {
let log = `console.log("------${appName}构建日志------")
console.log("开始时间:", ${startTime})
console.log("结束时间:", ${endTime})
`;
// 从 outputOptions 中拿到构建输出的目录
const filePath = `${outputOptions.path}/index.html`;
let content = fs.readFileSync(filePath, "utf-8");
const scriptPos = content.indexOf("</body>");
content = `${content.slice(
0,
scriptPos
)}<script>${log}</script>${content.slice(scriptPos)}`;
// 最后写入日志
fs.writeFileSync(filePath, content, "utf-8");
callback();
}
await axios.get(`/build-error`, {
appName,
});
callback();
});
}
}
module.exports = BuildInfoPlugin;
只需要把 tap
改为 tapAsync
, 我们在回调函数中增加 callback
。
完结
下一篇为大家带来 webpack loader
。
课后作业:如果是多页的情况,怎么给每个 html
增加构建信息?
转载自:https://juejin.cn/post/7268673775033843771