如果你曾经使用过webpack,你可能听说过webpack的插件。插件是扩展webpack的实施和架构的绝佳选择。如果你看看webpack的源代码,大约80%的代码是通过插件实现的。
<$>[注意]webpack还支持加载器
的概念,这有助于扩展webpack,并与解决器
一起工作,它们主要用于转换源代码,这是一个不同的主题,我可能会很快写一篇关于如何创建定制加载器的文章。
在深入了解创建自定义webpack插件的细节之前,我们需要了解模块包装器的一些基本操作以及webpack如何在帽子下工作。
在依赖性解决过程中,包装器进行模块映射(模块地图),将它们合并成一个文件,将其包装成一个模块. webpack以先进的方式执行这些部分,并添加一些其他步骤,以使其高效。
- 编译器:它具有顶级API,并为它们提供控制 Webpack 执行的链接
- 编译或依赖图表:由编译器返回,然后它开始创建依赖图表
- 解决器:创建提供的输入路径的绝对路径,并返回结果,请求,路径,背景等细节
- 解析器:它创建 AST(抽象语法树),然后寻找有趣的东西,如要求和导入,然后创建依赖对象
- 模块工厂:这些对象传递到模块Factory 函数并创建模块 模板:它执行模块数据绑定,并
webpack 为编译器、解析器和编译器提供链接,它使用一个名为 tapable的库,该库由 webpack 团队维护,并有助于创建强大而强大的链接,我们可以使用方法。
什么是Hooks和Tapping Into Methods?
Hooks 类似于事件,点击它们就像是倾听一个事件的听众开火并运行相应的方法,例如,当我们将 DOM 相关的事件听众放置时:
1window.addEventListener('load', (event) => {
2 loadEventListerner(event)
3});
在此,负载
是loadEventListener
正在触摸的事件或链接。
Webpack 如何使用 tapable & 如何插件进入图像?
让我们举一个现实世界的例子来解释 webpack 如何使用 tapable. 假设您正在从披萨送货应用程序订购披萨. 现在有一系列步骤涉及到这个过程,例如检查菜单,定制您的订单,然后最终通过支付它来订购。
在这个例子中,我们现在可以用 webpack代替披萨送货应用程序,自己用 webpack plugin和由 tapable创建的链接通知。
webpack 使用 tapable 创建了编译器、编译和分析阶段的链接,然后插件点击它们或倾听它们并相应地采取行动。
这些理论和概念,给我看代码!!!
对于这篇文章,我们将创建一个简单的webpack插件,它检查创建的包裹文件的大小,并根据大小限制记录错误或警告。这些大小限制也可以通过插件选项,我们将默认大小限制保持在3KB。
你可以找到此处的代码(https://github.com/alligatorio/bundlesize-webpack-plugin/tree/aligator-post)。
让我们先创建项目。
在您的项目目录中,使用 npm 或 Yarn 安装 webpack:
1$ npm init -y
2$ npm install webpack webpack-cli --save-dev
之后,创建一个src
目录,其中包含一个index.js
文件,您的输入或输入路径将指向并在项目根目录中创建一个webpack.config.js
文件。
现在你可以为你的插件创建一个目录,并将其命名为bundlesize-webpack-plugin
,并在该目录中创建一个index.js
。
您的项目结构应该看起来像这样:
1webpack-Plugin-demo-directory
2 |- webpack.config.js
3 |- package.json
4 |- /src
5 |- index.js
6 |- /bundlesize-webpack-plugin
7 |- index.js
将以下构建脚本添加到 package.json 文件中的脚本
:
1"build": "webpack"
在你的「bundlesize-webpack-plugin/index.js」中,写下以下代码:
1module.exports = class BundlesizeWebpackPlugin {
2 constructor(options) {
3 this.options = options;
4 }
5 apply(compiler) {
6 console.log("FROM BUNDLESIZE PLUGIN");
7 }
8};
我们将很快讨论这一点。
现在,在你的webpack.config.js中,写下以下代码:
1const { resolve } = require("path");
2const bundlesizeplugin = require("./bundlesize-webpack-plugin");
3
4module.exports = {
5 entry: resolve(__dirname, "src/index.js"),
6 output: {
7 path: resolve(__dirname, "bin"),
8 filename: "bundle.js"
9 },
10 plugins: [new bundlesizeplugin()]
11};
现在运行npm Run Build
。
您应该看到从BUNDLESIZE PLUGIN
消息出现在您的终端。
很棒,你刚刚创建了一个webpack插件!
打破它下来
每个webpack插件都必须有一个应用
方法,由webpack命名,webpack将编译器实例作为该方法的论点。
一个插件可以是基于类的,也可以是基于函数的。如果插件是基于函数,函数论点也同样是编译器。
您可以检查webpack的源代码以及它是如何实现的(https://github.com/webpack/webpack/blob/master/lib/webpack.js#L46-L51)
在类
构建器中,你可以看到有一个选项
论点. 这是当您的插件接受一些选项时使用的。 我们将通过sizeLimit
作为选项,如果没有通过,默认值将是3KB。
因此,我们现在可以将构建者方法更改为:
1constructor(options) {
2 this.options = options || {
3 sizeLimit: 3
4 };
5 }
您也可以通过sizeLimit
作为插件选项
,如下:
1plugins: [
2 new bundlesizeplugin({
3 sizeLimit: 4
4 })
5 ]
在webpack.config.js
中,我们只是提到输入点,并告诉webpack在一个bundle.js
文件中的名为bin
的文件夹中输出包裹文件,并告诉webpack从bundlesize-webpack-plugin
文件夹中使用我们的插件。
现在我们已经完成了项目,让我们检查资产大小,并与sizeLimit
进行比较. 我们将使用compiler.hooks.done
链接,当编译工作完成并生成包裹文件时发行。
請注意,有些子是非同步的,我們可以為他們使用非同步打擊方法。
1apply(compiler) {
2 compiler.hooks.done.tap("BundleSizePlugin", (stats) => {
3 const {
4 path,
5 filename
6 } = stats.compilation.options.output;
7 })
8 }
在这方面,我们正在点击编译器的已完成的链接或事件,方法中的第一个论点是webpack用于引用的插件名称,第二种方法是召回,将状态
作为一个论点。您可以使用console.log(stats)
来检查统计数据的内容,它将显示一个大对象,包含有关编译的所有可能的细节和该链接可用的文件。我们正在从输出属性中提取路径和文件名。从现在开始,它几乎只是使用Node.js的核心库路径
和fs
模块来获取文件的细节:
1apply(compiler) {
2 compiler.hooks.done.tap("BundleSizePlugin", stats => {
3 const { path, filename } = stats.compilation.options.output;
4 const bundlePath = resolve(path, filename);
5 const { size } = fs.statSync(bundlePath);
6 console.log(size); // size in bytes
7 });
8 }
简单的正确?
现在我们可以使用一个函数将字节大小转换为kb,例如从 This StackOverflow 答案转换的函数。
现在简单地将其与sizeLimit
和console.log
相应的消息进行比较:
1apply(compiler) {
2 compiler.hooks.done.tap("BundleSizePlugin", stats => {
3 const { path, filename } = stats.compilation.options.output;
4 const bundlePath = resolve(path, filename);
5 const { size } = fs.statSync(bundlePath);
6 const { bundleSize, fullSizeInfo } = formatBytes(size);
7 const { sizeLimit } = this.options;
8 if (bundleSize < sizeLimit) {
9 console.log(
10 "Safe:Bundle-Size",
11 fullSizeInfo,
12 "\n SIZE LIMIT:",
13 sizeLimit
14 );
15 } else {
16 if (bundleSize === sizeLimit) {
17 console.warn(
18 "Warn:Bundle-Size",
19 fullSizeInfo,
20 "\n SIZE LIMIT:",
21 sizeLimit
22 );
23 } else {
24 console.error(
25 "Unsafe:Bundle-Size",
26 fullSizeInfo,
27 "\n SIZE LIMIT:",
28 sizeLimit
29 );
30 }
31 }
32 });
33 }
你现在有自己的webpack插件,它根据尺寸限制检查包的大小和报告。
您现在可以在 npm 注册表上发布此信息。
您可以使用 webpack-default为一个好的起点。
请注意,我已经发布的 bundlesize-webpack-plugin也正在扩展自己的钩子,它们是使用可键入的创建的。
摘要
- 我们研究了webpack如何在帽子下工作,以及它的架构是如何实施的 *我们了解了和点击它们的含义 *我们看到插件如何进入系统 *我们制作了一个简单的插件来检查包装文件的大小