创建自定义 webpack 插件

如果你曾经使用过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 答案转换的函数。

现在简单地将其与sizeLimitconsole.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如何在帽子下工作,以及它的架构是如何实施的 *我们了解了和点击它们的含义 *我们看到插件如何进入系统 *我们制作了一个简单的插件来检查包装文件的大小
Published At
Categories with 技术
Tagged with
comments powered by Disqus