钩子函数: hookSeq
使用场景:onwrite、generateBundle等
钩子函数: hookParallel
使用场景:buildStart、buildEnd、renderStart等
钩子函数: hookReduceArg0
使用场景: outputOptions、renderChunk等
通过观察上面几种钩子函数的调用方式,我们可以发现,其内部有一个调用钩子函数的方法: runHook(Sync),该函数执行插件中提供的钩子函数。
实现很简单:
function runHook<T>( hookName: string, args: any[], pluginIndex: number, permitValues: boolean, hookContext?: ReplaceContext | null ): Promise<T> { this.previousHooks.add(hookName); // 找到当前plugin const plugin = this.plugins[pluginIndex]; // 找到当前执行的在plugin中定义的hooks钩子函数 const hook = (plugin as any)[hookName]; if (!hook) return undefined as any; // pluginContexts在初始化plugin驱动器类的时候定义,是个数组,数组保存对应着每个插件的上下文环境 let context = this.pluginContexts[pluginIndex]; // 用于区分对待不同钩子函数的插件上下文 if (hookContext) { context = hookContext(context, plugin); } return Promise.resolve() .then(() => { // permit values allows values to be returned instead of a functional hook if (typeof hook !== 'function') { if (permitValues) return hook; return error({ code: 'INVALID_PLUGIN_HOOK', message: `Error running plugin hook ${hookName} for ${plugin.name}, expected a function hook.` }); } // 传入插件上下文和参数,返回插件执行结果 return hook.apply(context, args); }) .catch(err => throwPluginError(err, plugin.name, { hook: hookName })); }当然,并不是每个人刚开始都会使用插件,所以rollup本身也提供了几个必需的钩子函数供我们使用,在Graph实例化的时候与用户自定义插件进行concat操作:
import { getRollupDefaultPlugin } from './defaultPlugin'; this.plugins = userPlugins.concat( // 采用内置默认插件或者graph的插件驱动器的插件,不管怎么样,内置默认插件是肯定有的 // basePluginDriver是上一个PluginDriver初始化的插件 // preserveSymlinks: 软连标志 basePluginDriver ? basePluginDriver.plugins : [getRollupDefaultPlugin(preserveSymlinks)] );那rollup提供了哪些必需的钩子函数呢:
export function getRollupDefaultPlugin(preserveSymlinks: boolean): Plugin { return { // 插件名 name: 'Rollup Core', // 默认的模块(文件)加载机制,内部主要使用path.resolve resolveId: createResolveId(preserveSymlinks) as ResolveIdHook, // this.pluginDriver.hookFirst('load', [id])为异步调用,readFile内部用promise包装了fs.readFile,并返回该promise load(id) { return readFile(id); }, // 用来处理通过emitFile添加的urls或文件 resolveFileUrl({ relativePath, format }) { // 不同format会返回不同的文件解析地址 return relativeUrlMechanisms[format](relativePath); }, // 处理import.meta.url,参考地址:https://nodejs.org/api/esm.html#esm_import_meta) resolveImportMeta(prop, { chunkId, format }) { // 改变 获取import.meta的信息 的行为 const mechanism = importMetaMechanisms[format] && importMetaMechanisms[format](prop, chunkId); if (mechanism) { return mechanism; } } }; }过一眼发现都是最基本处理路径解析内容的钩子函数。
不仅如此,rollup给钩子函数注入了context,也就是上下文环境,用来方便对chunks和其他构建信息进行增删改查。
中也写得很清楚,比如:
使用this.parse,调用rollup内部中的acron实例解析出ast
使用this.emitFile来增加产出的文件,看这个.