import type { LoadResult, PartialResolvedId, Plugin, ResolvedId, SourceDescription } from './plugin'; export interface PluginContainer { resolveId(id: string, importer?: string): Promise; load(id: string): Promise; transform(code: string, id: string): Promise; } // 模拟 Rollup 的插件机制 // 实现 Rollup 插件钩子的调度 // 实现插件钩子内部的 Context 上下文对象 export const createPluginContainer = (plugins: Plugin[]): PluginContainer => { // 插件上下文对象 // 使用implements来实现一些类共有方法属性的提取,能够提取类型中的属性。 // 这里仅实现上下文对象的 resolve 方法,缺少很多RollupPluginContext中的属性 class Context { async resolve(id: string, importer?: string) { let out = await pluginContainer.resolveId(id, importer); if (typeof out === 'string') out = { id: out }; return out as ResolvedId | null; } } // 插件容器 const pluginContainer: PluginContainer = { /** * @description: 调用插件本身的resolveId方法,解析文件地址,我们可以返回我们想返回的地址给ranite加载 * @param {string} id 文件路径 * @param {string} importer // 使用id文件路径的父路径 */ async resolveId(id: string, importer?: string) { const ctx = new Context(); for (const plugin of plugins) { if (plugin.resolveId) { const newId = await plugin.resolveId.call(ctx, id, importer); if (newId) { id = typeof newId === 'string' ? newId : newId.id; return { id }; } } } return null; }, /** * @description: 加载模块的内容 * @param {*} id 文件路径 * @return {*} */ async load(id) { const ctx = new Context(); for (const plugin of plugins) { if (plugin.load) { const result = await plugin.load.call(ctx, id); if (result) { return result; } } } return null; }, /** * @description: 自定义模块转换 * @param {*} code 转换前的文件内容 * @param {*} id 转换前的文件路径 * @return {*} */ async transform(code, id) { const ctx = new Context(); for (const plugin of plugins) { if (plugin.transform) { const result = await plugin.transform.call(ctx, code, id); if (!result) continue; if (typeof result === 'string') { code = result; } else if (result.code) { code = result.code; } } } return { code }; }, }; return pluginContainer; };