「这是我参与2022首次更文挑战的第5
天,活动详情查看:2022首次更文挑战 」。
前面我们已经学习了mode
,entry
,output
,loader
这些基本配置,接下来继续学习webpack最重要的一个基本配置:Plugin
Plugin(插件)
前文也提到,webpack有打包过程分为许多个步骤,每一个步骤都会有相对应的钩子。
plugin
的作用就是在钩子中添加对应的打包逻辑,当钩子触发会调用预先声明的函数。
Plugin与Loader的区别
与上一节我们学到的Loader
不同,Plugin
的用处比Loader
更广泛。
Loader
是让webpack支持除了js和json文件之外的文件处理。
Plugin
则是针对整个webpack打包的步骤去对对打包项目进行扩展和管理,包括但不限于打包优化,资源管理,注入环境变量。
Plugin的用法
聊完Plugin的基本概念,接下来看一下如何使用Plugin
,前面我们已经学会将模块打包成一个整体的文件,现在我们想要把js文件在打包完成之后自动地引入到html文件中
。
首先我们新建一个html模板:
<!DOCTYPE html>
<html lang="text/html">
<head>
<title>test</title>
<meta charset="utf-8" />
</head>
<body>
<p>Hello World</p>
</body>
</html>
在写两个简单的js文件
// entry.js
function test1() {
console.log("test1");
}
test1();
// test.js
function test2() {
console.log("test2");
}
test2();
编写webpack配置,将他们打包合并在一起,并且引用html-webpack-plugin
插件,将生成后的js文件写入html模板并输出。
const path = require("path");
const htmlPlugin = require("html-webpack-plugin");
module.exports = {
mode: "production",
entry: [
path.resolve(__dirname, "src", "entry.js"),
path.resolve(__dirname, "src", "test2.js"),
],
output: {
filename: "bundle.js",
},
plugins: [
new htmlPlugin({
template: path.resolve(__dirname, "src", "test.html"),
}),
],
};
打包后会出现两个文件,一个是js文件,另一个是基于模板html生成的html文件。并且html文件会带上打包后的js文件引用。
<!doctype html>
<html lang="text/html">
<head>
<title>test</title>
<meta charset="utf-8"/>
<script defer="defer" src="bundle.js"></script>
</head>
<body>
<p>Hello World</p>
</body>
</html>
编写一个Plugin
学会使用plugin
后,接下来深入地研究一下:plugin究竟是如何编写的。
plugin实际上是一个对象,对象中必须有一个apply
方法。
function MyPlugin() {
return {
apply(complier) {
complier.hooks.run.tap('MyPlugin', (compilation) => {
console.log('webpack is running!');
});
}
}
}
上面的代码就是一个最简单的webpack插件。
- 从代码中可以看到apply方法调用时,webpack会传入一个
complier
对象到方法中,complier
是webpack的主要引擎,他包含了生命周期钩子,webpack的配置等信息。 - 然后我们声明了一个在
run
生命周期的时候调用的方法。
当调用时,webpack会传入一个compilation
实例,它能够访问所有的模块和它们的依赖。
具体的compiler
和compilation
钩子参数,点击这里了解更多
了解了plugin是如何实现的,接下来我们就来写一个简单版的html-webpack-plugin
具体实现的功能:当打包完成后,生成一个script标签放入html文件中。
代码如下:
// plugin.js
const fs = require("fs");
const path = require("path");
function MyPlugin(templateName = "") {
return {
apply(complier) {
complier.hooks.run.tap("MyPlugin", (compilation) => {
const { outputPath } = compilation;
const fileName = compilation.options.output.filename;
const script = `<script lang="text/javascript" defer src="${fileName}"></script>`;
let fileChunk = fs.readFileSync(templateName, "utf-8");
fileChunk = fileChunk.replace("</head>", `${script}\n</head>`);
fs.writeFileSync(path.resolve(outputPath, "index.html"), fileChunk);
});
},
};
}
module.exports = MyPlugin;
// webpack.config.js
const path = require("path");
const htmlPlugin = require("html-webpack-plugin");
const MyPlugin = require("./src/plugin");
module.exports = {
mode: "production",
entry: [
path.resolve(__dirname, "src", "entry.js"),
path.resolve(__dirname, "src", "test2.js"),
],
output: {
filename: "bundle.js",
},
plugins: [new MyPlugin(path.resolve(__dirname, "src", "test.html"))],
};
小结
本小节讲述了plugin
的作用;plugin
与loader
的区别;用法和如何编写一个plugin。
plugin
的作用就是在钩子中添加对应的打包逻辑,在打包过程中进行一些额外的操作。loader
是让webpack支持其他文件的处理;plugin
是针对整个webpack打包的步骤去对对打包项目进行扩展。- 实现一个plugin,只需要返回一个对象,对象中包含一个
apply
方法即可
文章是从零开始学习webpack系列
的第四篇,其他章节可以看下面👇:
从零开始学习webpack5.x(一)
从零开始学习webpack5.x(二)
从零开始学习webpack5.x(三)
从零开始学习webpack5.x(四)
从零开始学习webpack5.x(五)
从零开始学习webpack5.x(六)