你必须知道的 webpack 插件原理分析,花了19998买的学习教程

plugin 的特征

webpack 插件有以下特征

  • 是一个独立的模块。

  • 模块对外暴露一个 js 函数。

  • 函数的原型 (prototype) 上定义了一个注入 compiler 对象的 apply 方法。

  • apply 函数中需要有通过 compiler 对象挂载的 webpack 事件钩子,钩子的回调中能拿到当前编译的 compilation 对象,如果是异步编译插件的话可以拿到回调 callback。

  • 完成自定义子编译流程并处理 complition 对象的内部数据。

  • 如果异步编译插件的话,数据处理完成后执行 callback 回调。

class HelloPlugin {

// 在构造函数中获取用户给该插件传入的配置

constructor(options) {}

// Webpack 会调用 HelloPlugin 实例的 apply 方法给插件实例传入 compiler 对象

apply(compiler) {

// 在emit阶段插入钩子函数,用于特定时机处理额外的逻辑;

compiler.hooks.emit.tap(‘HelloPlugin’, (compilation) => {

// 在功能流程完成后可以调用 webpack 提供的回调函数;

})

// 如果事件是异步的,会带两个参数,第二个参数为回调函数,

compiler.plugin(‘emit’, function (compilation, callback) {

// 处理完毕后执行 callback 以通知 Webpack

// 如果不执行 callback,运行流程将会一直卡在这不往下执行

callback()

})

}

}

module.exports = HelloPlugin

复制代码

  1. webpack 读取配置的过程中会先执行 new HelloPlugin(options) 初始化一个 HelloPlugin 获得其实例。

  2. 初始化 compiler 对象后调用 HelloPlugin.apply(compiler) 给插件实例传入 compiler 对象。

  3. 插件实例在获取到 compiler 对象后,就可以通过 compiler.plugin (事件名称, 回调函数) 监听到 Webpack 广播出来的事件。并且可以通过 compiler 对象去操作 Webpack。

事件流机制

webpack 本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来,而实现这一切的核心就是 Tapable

Webpack 的 Tapable 事件流机制保证了插件的有序性,将各个插件串联起来, Webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条 webapck 机制中,去改变 webapck 的运作,使得整个系统扩展性良好。

Tapable 也是一个小型的 library,是 Webpack 的一个核心工具。类似于 node 中的 events 库,核心原理就是一个订阅发布模式。作用是提供类似的插件接口。方法如下:

//  广播事件

compiler.apply(‘event-name’, params)

compilation.apply(‘event-name’, params)

// 监听事件

compiler.plugin(‘event-name’, function (params) {})

compilation.plugin(‘event-name’, function (params) {})

复制代码

我们来看下 Tapable

function Tapable() {

this._plugins = {}

}

//发布name消息

Tapable.prototype.applyPlugins = function applyPlugins(name) {

if (!this._plugins[name]) return

var args = Array.prototype.slice.call(arguments, 1)

var plugins = this._plugins[name]

for (var i = 0; i < plugins.length; i++) {

plugins[i].apply(this, args)

}

}

// fn订阅name消息

Tapable.prototype.plugin = function plugin(name, fn) {

if (!this._plugins[name]) {

this._plugins[name] = [fn]

} else {

this._plugins[name].push(fn)

}

}

//给定一个插件数组,对其中的每一个插件调用插件自身的apply方法注册插件

Tapable.prototype.apply = function apply() {

for (var i = 0; i < arguments.length; i++) {

arguments[i].apply(this)

}

}

复制代码

Tapable 为 webpack 提供了统一的插件接口(钩子)类型定义,它是 webpack 的核心功能库。webpack 中目前有十种 hooks,在 Tapable 源码中可以看到,他们是:

exports.SyncHook = require(‘./SyncHook’)

exports.SyncBailHook = require(‘./SyncBailHook’)

exports.SyncWaterfallHook = require(‘./SyncWaterfallHook’)

exports.SyncLoopHook = require(‘./SyncLoopHook’)

exports.AsyncParallelHook = require(‘./AsyncParallelHook’)

exports.AsyncParallelBailHook = require(‘./AsyncParallelBailHook’)

exports.AsyncSeriesHook = require(‘./AsyncSeriesHook’)

exports.AsyncSeriesBailHook = require(‘./AsyncSeriesBailHook’)

exports.AsyncSeriesLoopHook = require(‘./AsyncSeriesLoopHook’)

exports.AsyncSeriesWaterfallHook = require(‘./AsyncSeriesWaterfallHook’)

复制代码

Tapable 还统一暴露了三个方法给插件,用于注入不同类型的自定义构建行为:

  • tap:可以注册同步钩子和异步钩子。

  • tapAsync:回调方式注册异步钩子。

  • tapPromise:Promise 方式注册异步钩子。

webpack 里的几个非常重要的对象,CompilerCompilation 和 JavascriptParser 都继承了 Tapable 类,它们身上挂着丰富的钩子。

编写一个插件

一个 webpack 插件由以下组成:

  • 一个 JavaScript 命名函数。

  • 在插件函数的 prototype 上定义一个 apply 方法。

  • 指定一个绑定到 webpack 自身的事件钩子。

  • 处理 webpack 内部实例的特定数据。

  • 功能完成后调用 webpack 提供的回调。

下面实现一个最简单的插件

class WebpackPlugin1 {

constructor(options) {

this.options = options

}

apply(compiler) {

compiler.hooks.done.tap(‘MYWebpackPlugin’, () => {

console.log(this.options)

})

}

}

module.exports = WebpackPlugin1

复制代码

然后在 webpack 的配置中注册使用就行,只需要在 webpack.config.js 里引入并实例化就可以了:

const WebpackPlugin1 = require(‘./src/plugin/plugin1’)

module.exports = {

entry: {

index: path.join(__dirname, ‘/src/main.js’),

},

output: {

path: path.join(__dirname, ‘/dist’),

filename: ‘index.js’,

},

plugins: [new WebpackPlugin1({ msg: ‘hello world’ })],

}

复制代码

此时我们执行一下 npm run build 就能看到效果了

Compiler 对象 (负责编译)

Compiler 对象包含了当前运行 Webpack 的配置,包括 entryoutputloaders 等配置,这个对象在启动 Webpack 时被实例化,而且是全局唯一的。Plugin 可以通过该对象获取到 Webpack 的配置信息进行处理。

compiler 上暴露的一些常用的钩子:

下面来举个例子

class WebpackPlugin2 {

constructor(options) {

this.options = options

}

apply(compiler) {

compiler.hooks.run.tap(‘run’, () => {

console.log(‘开始编译…’)

})

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

总结

前端资料汇总

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。

  • 算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯

  • 在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。

  • 要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
    喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!
    面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**

  • 框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。

  • 算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯

  • 在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。

  • 要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
    喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值