钩子
一、认识
1.1 构建阶段
插件的各种 Hook
可以根据这两个构建阶段分为两类: Build Hook
与 Output Hook
。
-
Build Hook
: 即在Build阶段执行的钩子函数,在这个阶段主要进行模块代码的转换、AST
解析以及模块依赖的解析,那么这个阶段的Hook
对于代码的操作粒度一般为模块级别,也就是单文件级别。 -
Output Hook
: (官方称为Output Generation Hook
),则主要进行代码的打包,对于代码而言,操作粒度一般为chunk
级别(一个chunk
通常指很多文件打包到一起的产物)。
1.2 执行方式
除了根据构建阶段可以将 Rollup
插件进行分类,根据不同的 Hook
执行方式也会有不同的分类,主要包括Async
、Sync
、Parallel
、Sequential
、First
这五种。在后文中我们将接触各种各样的插件 Hook
,但无论哪个 Hook
都离不开这五种执行方式。
-
Async & Sync
: 首先是Async
和Sync
钩子函数,两者其实是相对的,分别代表异步和同步的钩子函数,两者最大的区别在于同步钩子里面不能有异步逻辑,而异步钩子可以有。 -
Parallel
: 这里指并行的钩子函数。如果有多个插件实现了这个钩子的逻辑,一旦有钩子函数是异步逻辑,则并发执行钩子函数,不会等待当前钩子完成(底层使用Promise.all
)。比如对于Build
阶段的buildStart
钩子,它的执行时机其实是在构建刚开始的时候,各个插件可以在这个钩子当中做一些状态的初始化操作,但其实插件之间的操作并不是相互依赖的,也就是可以并发执行,从而提升构建性能。反之,对于需要依赖其他插件处理结果的情况就不适合用Parallel
钩子了,比如transform
。 -
Sequential
: 指串行的钩子函数。这种Hook
往往适用于插件间处理结果相互依赖的情况,前一个插件Hook
的返回值作为后续插件的入参,这种情况就需要等待前一个插件执行完Hook
,获得其执行结果,然后才能进行下一个插件相应Hook
的调用,如transform
。 -
First
: 如果有多个插件实现了这个Hook
,那么Hook
将依次运行,直到返回一个非null
或非undefined
的值为止。比较典型的Hook
是resolveId
,一旦有插件的resolveId
返回了一个路径,将停止执行后续插件的resolveId
逻辑。
1.3 this 上下文
二、options
首先经历 options
钩子进行配置的转换,得到处理后的配置对象。
三、buildStart
**Rollup
会调用 buildStart
钩子,正式开始构建流程。
四、resolveId
Rollup
先进入到 resolveId
钩子中解析文件路径。(从 input
配置指定的入口文件开始)。resolveId
钩子一般用来解析模块路径,为Async + First
类型即异步优先的钩子。
4.1 语法
function Plugin(options){
return {
name: "rollup-plugin-xxx",
// 传入三个参数,当前模块路径、引用当前模块的模块路径、其余参数
resolveId(importee, importer, resolveOptions){
}
}
}
-
参数:
-
importee
: 当前模块路径 -
importer
: 引用当前模块的模块路径 -
resolveOptions
: 解析参数
-
-
返回值: 返回值可以是
null
、string
或者一个对象-
返回值为
null
时,会默认交给下一个插件的resolveId
钩子处理。 -
返回值为
string
时,则停止后续插件的处理。这里为了让替换后的路径能被其他插件处理,特意调用了this.resolve
来交给其它插件处理,否则将不会进入到其它插件的处理。 -
返回值为一个对象,也会停止后续插件的处理,不过这个对象就可以包含更多的信息了,包括解析后的路径、是否被
enternal
、是否需要tree-shaking
等等,不过大部分情况下返回一个string
就够用了。
-
五、load
Rollup
通过调用 load
钩子加载模块内容。load
为 Async + First
类型,即异步优先的钩子,和 resolveId
类似。它的作用是通过 resolveId
解析后的路径来加载模块内容。
5.1 语法
function Plugin(options){
return {
name: "rollup-plugin-xxx",
load(id){
}
}
}
-
参数:
id
:
-
返回值: 返回值一般是
null
、string
或者一个对象