当前位置: 首页 > news >正文

Webpack 特性:自定义 Loader 和 Plugin

文章目录

    • 前言:
    • Loader
    • Webpack生命周期:
    • Tapable
      • 安装 Tapable
      • 钩子的类型
      • 使用 Tapable
        • 同步钩子(SyncHook)
        • 异步钩子
          • AsyncParallelHook
          • AsyncSeriesHook
      • 钩子的拦截器(Interceptor)
    • 自定义 Plugin 的实现:

前言:

Webpack是一个现代JavaScript应用的静态模块打包器,它能够将项目中的所有依赖项(包括JavaScript、图片、CSS等)打包成一个或多个bundle
在Webpack的构建过程中,存在许多生命周期钩子(hooks),这些钩子允许插件(plugins)和loaders在不同阶段介入构建过程。

Loader

  • 一个模块转换器它使得 Webpack 能够处理非 JavaScript 文件。Loader 在import模块时被调用,并且可以链式调用,形成一个处理流程。
  • Loader 通常用于转换文件,比如将 Sass 文件转换为 CSS,或者将图像文件转换为 DataURL。
  • Loader本身是一个函数,它接收源文件作为输入,输出转换后的文件内容。

自定义 Loader 的实现

我们现在的需求是,将 Markdown 文件转换为 HTML, 实现步骤

  1. 创建一个 JavaScript 文件作为 Loader,比如my-loader.js
  2. 在这个文件中,导出一个函数,这个函数将对文件资源进行处理。
  3. 在 Webpack 配置文件中webpack.config.js,添加一个规则,指定该 Loader 应用到特定的文件类型上。
// my-loader.js
const marked = require("marked");
module.exports = function (source) {// 使用marked将markdown转换为htmlconst html = marked(source);return html;
};

然后在webpack.config.js中配置这个 Loader:

// webpack.config.js
module.exports = {module: {rules: [{test: /\.md$/,use: "./my-loader",},],},
};

Webpack生命周期:

在写plugin之前,我们先回顾下 webpack的 生命周期和内部使用的TapTable的库(用于处理事件注册和触发的)

Webpack的生命周期主要分为两个部分:Compiler 生命周期和Compilation 生命周期。

  • Compiler 生命周期是关于整个构建过程的,例如:

    • beforeRun:在开始编译之前调用。
    • run:在编译开始时调用。
    • emit:在所有资源被emit到发输目录之前调用。
    • done:在编译完成之后调用。
  • Compilation 生命周期是关于单独一次编译的,例如:

    • buildModule:在模块开始构建时调用。
    • normalModuleFactory:在模块工厂创建时调用。
    • seal:在编译完成,优化阶段开始之前调用。

Tapable

Tapable 是一个基于发布订阅模式实现的事件系统,Webpack 中的插件(Plugins)就是使用 Tapable 来监听和改变构建流程, Tapable允许开发者创建自定义的钩子,并且可以在这些钩子上注册监听函数,这些函数将在钩子被触发时执行。

Tapable 提供了多种类型的钩子,分为同步异步两大类,每种类型又有不同的行为。

安装 Tapable

首先,你需要安装 Tapable:

npm install --save tapable

钩子的类型

  • SyncHook: 同步执行,无返回值。
  • SyncBailHook: 同步执行,返回非 undefined 则中断。
  • SyncWaterfallHook: 同步执行,返回值会传递给下一个回调。
  • SyncLoopHook: 同步执行,返回非 undefined 则重新执行当前回调。
  • AsyncParallelHook: 异步并行执行。
  • AsyncParallelBailHook: 异步并行执行,有返回值则中断。
  • AsyncSeriesHook: 异步串行执行。
  • AsyncSeriesBailHook: 异步串行执行,有返回值则中断。
  • AsyncSeriesWaterfallHook: 异步串行执行,返回值会传递给下一个回调。

使用 Tapable

同步钩子(SyncHook)

Sync 类型 “钩子” 执行的插件都是顺序执行的,并且只能使用 tap 注册,可以使用 call 调用。

const { SyncHook } = require('tapable');const hook = new SyncHook(['arg1', 'arg2']);
hook.tap('myPlugin', (arg1, arg2) => {console.log(`myPlugin: ${arg1}, ${arg2}`);
});hook.call('hello', 'world'); // 输出:myPlugin: hello, world
异步钩子

异步钩子可以注册异步的回调函数,分为并行(AsyncParallelHook)串行(AsyncSeriesHook)两种。

AsyncParallelHook

并行执行所有注册的异步回调,所有回调完成后执行最终的回调。

const { AsyncParallelHook } = require('tapable');const hook = new AsyncParallelHook(['arg1']);
hook.tapAsync('myAsyncPlugin', (arg1, callback) => {setTimeout(() => {console.log(`myAsyncPlugin: ${arg1}`);callback();}, 1000);
});hook.callAsync('test', () => {console.log('所有任务执行完毕.');
});
AsyncSeriesHook

串行执行所有注册的异步回调,每个回调完成后,才会执行下一个。

const { AsyncSeriesHook } = require('tapable');const hook = new AsyncSeriesHook(['arg1']);
hook.tapAsync('mySeriesPlugin', (arg1, callback) => {setTimeout(() => {console.log(`mySeriesPlugin: ${arg1}`);callback();}, 1000);
});hook.callAsync('test', () => {console.log('所有任务执行完毕.');
});

钩子的拦截器(Interceptor)

Tapable 还允许你为钩子添加拦截器,可以在钩子执行前后添加自定义逻辑。

const hook = new SyncHook(['arg1', 'arg2']);
hook.intercept({call: (arg1, arg2) => {console.log(`Before call: ${arg1}, ${arg2}`);},tap: (tapInfo) => {console.log(`Tap registered: ${tapInfo.name}`);}
});

自定义 Plugin 的实现:

  1. 创建一个 JavaScript 文件作为 Plugin,比如my-plugin.js
  2. 在这个文件中,定义一个类,这个类必须实现apply方法。
  3. apply方法中,接受compiler参数,我们可以在上面注册我们的事件,并执行自定义逻辑。
// my-plugin.js
class MyPlugin {apply(compiler) {compiler.hooks.done.tap("MyPlugin", (stats) => {console.log("构建完成!");// 这里可以执行一些构建完成后的逻辑// 将打包后的代码上传至 minio, 方便下载});}
}
module.exports = MyPlugin;

然后在webpack.config.js中配置这个 Plugin:

// webpack.config.js
const MyPlugin = require("./my-plugin");
module.exports = {plugins: [new MyPlugin()],
};

http://www.mrgr.cn/news/41619.html

相关文章:

  • 【C++二分查找 前缀和】1712. 将数组分成三个子数组的方案数|2078
  • 付费计量系统通用功能(9)
  • ERC 是什么?
  • 什么是虚拟化?| 裸机 vs 虚拟机 vs 容器
  • 免费录屏软件工具:助力高效屏幕录制
  • 数字控制系统
  • 媲美GPT-4o mini的小模型,Meta Llama 3.2模型全面解读!
  • `address-profile-spec-alias-ref` 元素
  • Golang | Leetcode Golang题解之第452题用最少数量的箭引爆气球
  • Python练习1
  • 在Ubuntu 16.04上使用LAMP安装WordPress
  • 死锁的成因与解决方案
  • 大豆虫害检测数据集 1800张 大豆虫害 带标注 voc yolo 12类
  • 学生课堂行为检测数据集 8800张 上课行为 标注voc yolo 7类
  • Pikachu-csrf-CSRF(get)
  • 特权访问管理阻力最小的途径
  • linux自用小手册
  • stack、heap、.bss、.data、.text
  • Pikachu-csrf-CSRF(POST)
  • Pikachu-xss防范措施 - href输出 js输出