自定义字体 webpack_创建一个自定义Webpack插件

news/2024/7/6 1:59:40

自定义字体 webpack

If you’ve ever worked with webpack, you’ve probably heard of webpack plugins. Plugins are a great option for extending webpack’s implementation and architecture. If you look at webpack’s source code, around 80% of their code is implemented using plugins. It helps in separating the core part of webpack, which leads to better code maintenance.

如果您曾经使用过webpack,则可能听说过webpack插件。 插件是扩展webpack的实现和体系结构的绝佳选择。 如果您查看webpack的源代码,则大约80%的代码是使用插件实现的。 它有助于分离webpack的核心部分,从而导致更好的代码维护。

webpack also supports the concepts of loaders which help in extending webpack too and work along with resolvers. They are mainly used to transform the source code. It’s a different topic to cover and I’ll probably write an article about how to create a custom loader pretty soon too.

webpack还支持loaders的概念,该概念也有助于扩展webpack并与resolvers一起使用。 它们主要用于转换源代码。 这是一个不同的主题,我可能很快也会写一篇有关如何创建自定义加载器的文章。

Before going into details about creating custom webpack plugins, we need to know some basic workings of a module bundler and how webpack works under the hood. The goal of a basic module bundler is to read the source code, find the dependencies - this is called dependency resolution.

在详细介绍创建自定义Webpack插件之前,我们需要了解模块捆绑器的一些基本工作原理以及webpack的工作原理。 基本模块捆绑器的目标是阅读源代码,找到依赖关系-这称为依赖关系解析

During the dependency resolution, the bundler does module mapping (module map), bundling them into one file, packaging it into one module. webpack does these parts in an advanced way and adds some other steps too in order to make it efficient. We can break the architecture of webpack using the following steps:

在依赖性解析期间,捆绑程序执行模块映射( module map ),将它们捆绑到一个文件中,然后将其打包到一个模块中。 webpack会以高级方式执行这些部分,并添加一些其他步骤以使其高效。 我们可以使用以下步骤来破坏webpack的体系结构:

  • Compiler: it has the top-level API and provides hooks for them for controlling the execution of webpack.

    编译器 :它具有顶级API,并为它们提供了用于控制webpack执行的挂钩。

  • Compilation or dependency graph: returned by the compiler and it starts creating the dependency graph.

    编译或依赖图 :由编译器返回,并开始创建依赖图。

  • Resolver: creates an absolute path for the entry path provided and return details like results, request, path, context, etc.

    解析器 :为提供的输入路径创建一个绝对路径,并返回详细信息,例如结果,请求,路径,上下文等。

  • Parser: it creates the AST (abstract syntax tree) and then looks for interesting thing like requires and imports and then creates the dependency object.

    解析器 :它创建AST(抽象语法树),然后查找诸如require和import之类的有趣事物,然后创建依赖项对象。

  • Module Factories: These objects are passed to the moduleFactory function and creates the module.

    模块工厂 :将这些对象传递给moduleFactory函数并创建模块。

  • Templates: it does the data binding of the module object and create the code in the bundled file.

    模板 :它执行模块对象的数据绑定,并在捆绑的文件中创建代码。

webpack provides hooks for the compiler, parser, and compilations. It uses a library called tapable, which is maintained by the webpack team and helps in creating strong and powerful hooks where we can tap into methods.

webpack为编译器,解析器和编译提供挂钩。 它使用了一个名为tapable的库,该库由webpack团队维护,并有助于创建强大而强大的钩子,我们可以在其中插入方法。

什么是钩子和挖掘方法? (What are Hooks and Tapping Into Methods?)

Hooks are similar to events and tapping into them is like listeners listening for an event to fire and run the appropriate method. For example when we place DOM-related event listeners like this:

挂钩类似于事件,轻按它们就像侦听器在侦听要触发的事件并运行适当的方法一样。 例如,当我们像这样放置与DOM相关的事件侦听器时:

window.addEventListener('load', (event) => {
  loadEventListerner(event)
});

In this, load is an event or hook in which loadEventListener is tapping into.

在这种情况下, load是一个事件或钩子, loadEventListener正在其中进入。

webpack如何使用可点击视频以及插件如何进入图片? (How webpack Uses tapable & How Plugins Coming Into the Picture?)

Let’s take a real-world example to explain how webpack uses tapable. Let’s say you are ordering pizza from a pizza delivery app. Now there are a series of steps involved with the process it like checking the menu, customizing your order and then finally placing the order by paying for it. Now from here onwards and until delivering your pizza to you, the app sends you notifications about the order progress.

让我们以一个真实的例子来说明webpack如何使用Tapable。 假设您要从披萨递送应用程序订购披萨。 现在,该过程涉及一系列步骤,例如检查菜单,自定义您的订单,然后最终通过付款来下订单。 从现在开始,直到将披萨交付给您,该应用都会向您发送有关订单进度的通知。

In this example, we can now replace the pizza delivery app with webpack, yourself with a webpack plugin and notifications with hooks created by tapable.

在此示例中,我们现在可以用webpack替换披萨递送应用程序,用webpack插件替换您自己的比萨饼应用程序,并使用tapable创建的挂钩替换通知。

webpack creates hooks for the compiler, compilations and parser stages using tapable and then the plugin taps into them or listens for them and acts accordingly.

webpack使用tapable为编译器 , 编译和解析器阶段创建钩子,然后插件将它们插入或监听它们并采取相应的措施。

Enough of these theories and concepts, show me the code !!

这些理论和概念足够多,请向我展示代码!

For this post, we’ll create a simple webpack plugin that checks the size of the bundled file created and logs errors or warnings based on a size limit. Those size limits can be passed in the plugin options as well and we’ll keep the default size limit to 3KB. So whenever the output file plugin is exceeding the size limit, we’ll log an error message and if it’s below it, we will log a safe message and if it’s equal to the size limit, we will simply warn the user.

在本文中,我们将创建一个简单的webpack插件,该插件可检查创建的捆绑文件的大小,并根据大小限制记录错误或警告。 这些大小限制也可以在插件选项中传递,我们会将默认大小限制保持为3KB。 因此,每当输出文件插件超过大小限制时,我们都会记录一条错误消息,如果该消息低于该大小限制,我们将记录一条安全消息,如果它等于大小限制,我们将仅警告用户。

You can find the code for the plugin here.

您可以在此处找到该插件的代码 。

让我们先设置项目。 (Let’s Setup the Project First.)

In your project directory, install webpack using npm or Yarn:

在您的项目目录中,使用npm或Yarn安装webpack:

$ npm init -y
$ npm install webpack webpack-cli --save-dev

After this, create an src directory with a index.js file in it, where your input or entry path will point to and create a webpack.config.js file in your project root directory.

此后,在其中创建一个带有index.js文件的src目录,您的输入或输入路径将指向该目录,并在项目根目录中创建一个webpack.config.js文件。

Now you can create a directory for your plugin and name it something like bundlesize-webpack-plugin and create a index.js inside that directory.

现在,您可以为插件创建一个目录,并将其命名为bundlesize-webpack-plugin然后在该目录中创建index.js

Your project structure should look something like this:

您的项目结构应如下所示:

webpack-Plugin-demo-directory
  |- webpack.config.js
  |- package.json
  |- /src
    |- index.js
  |- /bundlesize-webpack-plugin
    |- index.js

Add the following build script to the scripts in your package.json file:

将以下构建脚本添加到package.json文件中的scripts中:

"build": "webpack"

And in your bundlesize-webpack-plugin/index.js write the following code:

然后在您的bundlesize-webpack-plugin/index.js编写以下代码:

module.exports = class BundlesizeWebpackPlugin {
 constructor(options) {
   this.options = options;
 }
 apply(compiler) {
   console.log("FROM BUNDLESIZE PLUGIN");
 }
};

We will discuss this soon.

我们将尽快讨论。

Now in your webpack.config.js, write the following code:

现在在您的webpack.config.js ,编写以下代码:

const { resolve } = require("path");
const bundlesizeplugin = require("./bundlesize-webpack-plugin");

module.exports = {
 entry: resolve(__dirname, "src/index.js"),
 output: {
   path: resolve(__dirname, "bin"),
   filename: "bundle.js"
 },
 plugins: [new bundlesizeplugin()]
};

Now run npm run build.

现在运行npm run build

You should see the “FROM BUNDLESIZE PLUGIN” message appear in your terminal.

您应该在终端上看到“ FROM BUNDLESIZE PLUGIN”消息。

Great, you’ve just made a webpack plugin!

太好了,您刚刚制作了一个Webpack插件!

分解 (Breaking it down)

Every webpack plugin must have an apply method in them which is called by webpack and webpack gives the compiler instance as an argument to that method.

每个webpack插件中都必须有一个apply方法,该方法由webpack调用,并且webpack会将编译器实例作为该方法的参数。

A plugin can be class-based or can be function-based. If the plugin is function-based, the function argument is again compiler as well. We’ll go with class-based for this article as that is the recommended way.

插件可以基于类,也可以基于函数。 如果插件是基于函数的,那么function参数也是编译器。 我们建议您使用基于类的文章,因为这是推荐的方法。

You can check the webpack’s source code and how it’s implemented here

您可以在此处查看webpack的源代码及其实现方式

In the class’ constructor, you can see there is an options argument. This is used when your plugin accepts some options. We’ll pass the sizeLimit as an option and if it’s not passed the default will be 3KB.

在类的构造函数中,您可以看到有一个options参数。 当您的插件接受某些选项时使用。 我们将通过sizeLimit作为选项,如果未通过,则默认值为3KB 。

So we can now change the constructor method to this:

现在我们可以将构造方法更改为:

constructor(options) {
   this.options = options || {
     sizeLimit: 3
   };
 }

You can pass the sizeLimit as plugin options as well, like this:

您也可以将sizeLimit作为插件options传递,如下所示:

plugins: [
   new bundlesizeplugin({
     sizeLimit: 4
   })
 ]

In webpack.config.js, we are simply mentioning the entry point and telling webpack to output the bundle file in a folder named bin in a bundle.js file, and telling webpack to use our plugin from the bundlesize-webpack-plugin folder.

webpack.config.js ,我们只是提切入点,告诉的WebPack输出在命名的文件夹的包文件binbundle.js文件,并告诉的WebPack使用我们的插件从bundlesize-webpack-plugin文件夹中。

Now that we have the project ready, let’s check for asset size and compare with the sizeLimit. We’re going to use the compiler.hooks.done hook which is emitted when the compilation work is done and the bundled file is generated. We can get the details about the bundled file that way.

现在我们已经准备好项目,让我们检查资产大小并与sizeLimit进行比较。 我们将使用compiler.hooks.done挂钩,该挂钩在编译工作完成并生成捆绑文件时发出。 我们可以通过这种方式获取有关捆绑文件的详细信息。

Note that there are some hooks which are asynchronous and we can use an asynchronous tapping method for them. You can learn about these here

请注意,有一些异步钩子,我们可以为它们使用异步攻丝方法。 您可以在这里了解这些

apply(compiler) {
   compiler.hooks.done.tap("BundleSizePlugin", (stats) => {
     const {
        path,
        filename
     } = stats.compilation.options.output;
   })
 }

In this, we are tapping into the done hook or event of the compiler, the first argument in the method is the plugin name which is used by webpack for referencing and the second method is the callback which takes stats as an argument. You can check the content of the stats using console.log(stats), it will show a large object with every possible detail about the compilation and the file available for that hook. We are extracting the path and the filename from the output property. From now on, it’s pretty much just about getting details for the file using Node.js’ core library path and fs modules:

在此,我们利用了编译器的完成挂钩或事件,该方法中的第一个参数是插件名称,webpack使用该插件名称进行引用,第二个方法是将stats作为参数的回调。 您可以使用console.log(stats)来检查统计信息的内容,它将显示一个大对象,其中包含有关该挂钩和该挂钩可用文件的所有可能的详细信息。 我们正在从输出属性中提取路径和文件名。 从现在开始,几乎就是使用Node.js的核心库pathfs模块获取文件的详细信息:

apply(compiler) {
   compiler.hooks.done.tap("BundleSizePlugin", stats => {
     const { path, filename } = stats.compilation.options.output;
     const bundlePath = resolve(path, filename);
     const { size } = fs.statSync(bundlePath);
     console.log(size); // size in bytes
   });
 }

Simple right?

简单吧?

Now we can convert the size from bytes to kb using using a function like the one from this StackOverflow answer.

现在,我们可以使用类似于StackOverflow答案中的函数将大小从字节转换为kb。

Now simply compare it with the sizeLimit and console.log the appropriate message:

现在,只需将其与sizeLimit进行比较,然后console.log相应的消息:

apply(compiler) {
   compiler.hooks.done.tap("BundleSizePlugin", stats => {
     const { path, filename } = stats.compilation.options.output;
     const bundlePath = resolve(path, filename);
     const { size } = fs.statSync(bundlePath);
     const { bundleSize, fullSizeInfo } = formatBytes(size);
     const { sizeLimit } = this.options;
     if (bundleSize < sizeLimit) {
       console.log(
         "Safe:Bundle-Size",
         fullSizeInfo,
         "\n SIZE LIMIT:",
         sizeLimit
       );
     } else {
       if (bundleSize === sizeLimit) {
         console.warn(
           "Warn:Bundle-Size",
           fullSizeInfo,
           "\n SIZE LIMIT:",
           sizeLimit
         );
       } else {
         console.error(
           "Unsafe:Bundle-Size",
           fullSizeInfo,
           "\n SIZE LIMIT:",
           sizeLimit
         );
       }
     }
   });
 }

That’s it! You now have your own webpack plugin which checks for the bundle size and reports based on the size limit.

而已! 现在,您有了自己的webpack插件,该插件可检查捆绑包的大小并根据大小限制进行报告。

You can now publish this on the npm registry.

现在,您可以在npm注册表上发布它。

There are few standards that webpack finds effective to have in plugins. You can use webpack-default for a good starting point.

Webpack认为在插件中有效的标准很少。 您可以使用webpack-default作为一个很好的起点。

Note that the bundlesize-webpack-plugin, which I’ve published already, is also extending hooks of its own and they are created using tapable. You can find the implementation in the master branch.

请注意,我已经发布的bundlesize-webpack-plugin也在扩展它自己的钩子,它们是使用tapable创建的。 您可以在master分支中找到实现。

摘要 (Summary)

  • We went over how webpack works under the hood and how its architecture is implemented

    我们讨论了webpack的工作原理以及其架构的实现方式
  • We learned about hooks and what it means to tap into them

    我们了解了钩子以及使用钩子的含义
  • We saw how plugins come into the system

    我们看到了插件如何进入系统
  • We made a simple plugin to check the size of the bundled file

    我们制作了一个简单的插件来检查捆绑文件的大小

翻译自: https://www.digitalocean.com/community/tutorials/js-create-custom-webpack-plugin

自定义字体 webpack


http://www.niftyadmin.cn/n/3649552.html

相关文章

[ustc]那些杀手不太冷

喜欢fail学生的教授叫杀手。如果一个学校没几个杀手&#xff0c;断然没有资格叫名校。既然叫杀手&#xff0c;可想而知学生有多痛恨这些变态教授&#xff0c;然而毕业之后&#xff0c;我们却发现&#xff0c;我们很感激那些冷血残酷的杀手。科大建校第一天就无愧于名校之称&…

golang 结构体标签_如何在Go中使用结构标签

golang 结构体标签介绍 (Introduction) Structures, or structs, are used to collect multiple pieces of information together in one unit. These collections of information are used to describe higher-level concepts, such as an Address composed of a Street, City…

Windows 软件卸载清理工具 Geek Uninstaller

今天推荐一款好用的Windows系统下的软件卸载清理工具—&#xff1a;Geek Uninstaller 有时电脑遇到软件无法卸载&#xff0c; 软件残留注册表影响软件安装。 软件繁多&#xff0c;难于统一管理&#xff1f; Geek Uninstaller都可以解决。 软件免安装&#xff0c;单文件打开…

[EntLib]UAB(Updater Application Block)下载

下载地址&#xff1a;http://www.microsoft.com/downloads/details.aspx?FamilyIdC6C09314-E222-4AF2-9395-1E0BD7060786&displaylangenFile Name:ApplicationUpdater2.msiVersion: 2.0Date Published:4/8/2005UAB(Updater Application Block)&#xff0c;你可以用它来从中…

【ARM Coresight 系列文章 3.1 - ARM Coresight DP 对 AP 的访问 1】

文章目录 1.1 DP 中相关寄存器的介绍1.1.1 DPACC and APACC 寄存器1.1.2 DP SELECT 寄存器1.1.3 AP CSW寄存器1.1.4 AP TAR 寄存器1.1.5 AP DRW寄存器1.1.6 AP Banked Data registers 1.1 DP 中相关寄存器的介绍 如果DAP接入的是JTAG接口&#xff0c;那么将会通过APACC寄存器来…

华为鸿蒙系统应用开发工具介绍 DevEco Studio

简单介绍华为鸿蒙系统应用开发工具 DevEco Studio的安装和使用 据说12月份鸿蒙系统会推出手机的SDK哦&#xff0c;作为一名普通的开发者&#xff0c;表示非常期待。 一、HUAWEI DevEco Studio 介绍 HUAWEI DevEco Studio 是华为消费者业务为开发者提供的集成开发环境&#xf…

go语言结构体数组定义_在Go中定义结构

go语言结构体数组定义介绍 (Introduction) Building abstractions around concrete details is the greatest tool that a programming language can give to a developer. Structs allow Go developers to describe the world in which a Go program operates. Instead of rea…

[Java] 利用xpdf库获取pdf文件的指定范围文本内容

[Java] 利用xpdf库获取pdf文件的指定范围文本内容编写者日期关键词郑昀ultrapower2005-8-2Java PDF xpdf读取PDF文件的某一部分文本内容&#xff0c;可以使用开源项目xpdf。从Java中调用xpdf&#xff0c;我们参照了《Java抽取Word&#xff0c;PDF的四种武器》文章最后提到的办法…