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

网站显示百度地图门户网站建设兴田德润

网站显示百度地图,门户网站建设兴田德润,做网站运营有前景吗,无代码开发平台 免费文章目录 GraphPluginDriver生成 PluginDriver 实例和 PluginCache 缓存创建插件上下文 pluginContext初始化 pluginContext 缓存设置、方法插件中使用缓存可替换的 replace pluginContextPluginDriver 提供 asyn、first、parallel 等类型 hookgetSortedPlugins 运行时收集并存…

文章目录

  • Graph
  • PluginDriver
    • 生成 PluginDriver 实例和 PluginCache 缓存
    • 创建插件上下文 pluginContext
    • 初始化 pluginContext 缓存设置、方法
    • 插件中使用缓存
    • 可替换的 replace pluginContext
    • PluginDriver 提供 asyn、first、parallel 等类型 hook
      • getSortedPlugins 运行时收集并存储插件对应 hook
      • sync hook
      • parallel hook
    • this.runHookSync
    • this.runHook
  • 和 webpack 插件系统区别

Graph

  • 在依赖图谱 Graph 中创建 PluginDriver
  • Graph 负责整个 Rollup 打包过程中模块的解析、转化、生成,所以在Graph 中创建 PlunginDriver 能够获得整个打包生命周期的模块信息
	const graph = new Graph(inputOptions, watcher);

PluginDriver

生成 PluginDriver 实例和 PluginCache 缓存

  • 整个 Rollup 构建生命周期中,通过 pluginDriver 这个实例去触发 hook
export default class Graph {readonly acornParser: typeof acorn.Parser;readonly cachedModules = new Map<string, ModuleJSON>();// ...entryModules: Module[] = [];readonly fileOperationQueue: Queue;readonly moduleLoader: ModuleLoader;readonly modulesById = new Map<string, Module | ExternalModule>();needsTreeshakingPass = false;phase: BuildPhase = BuildPhase.LOAD_AND_PARSE;readonly pluginDriver: PluginDriver;// ...constructor (private readonly options: NormalizedInputOptions, watcher: RollupWatcher | null) {// 根据用户设置配置插件缓存this.pluginCache = options.cache?.plugins || Object.create(null);// ...this.pluginDriver = new PluginDriver(this, options, options.plugins, this.pluginCache); // 给插件封装能调用 graph 的方法// ...}

创建插件上下文 pluginContext

  • pluginContext 是交给用户在插件中可以调用的相关方法、属性
  • 可以看到多个插件的上下文共享同一个 pluginCache、graph
export class PluginDriver {// ... 相关方法private readonly pluginContexts: ReadonlyMap<Plugin, PluginContext>;private readonly plugins: readonly Plugin[];private readonly sortedPlugins = new Map<AsyncPluginHooks, Plugin[]>();private readonly unfulfilledActions = new Set<HookAction>();constructor(private readonly graph: Graph,private readonly options: NormalizedInputOptions,userPlugins: readonly Plugin[],private readonly pluginCache: Record<string, SerializablePluginCache> | undefined,basePluginDriver?: PluginDriver) {// ...this.plugins = [...(basePluginDriver ? basePluginDriver.plugins : []), ...userPlugins];const existingPluginNames = new Set<string>();// 为每个插件创建一个 pluginContext this.pluginContexts = new Map(this.plugins.map(plugin => [plugin,getPluginContext(plugin, pluginCache, graph, options, this.fileEmitter, existingPluginNames)]));// ...}
}

初始化 pluginContext 缓存设置、方法

  • 将每个 plugin 按照传递的配置设置缓存 key,存放进 Graph 的 pluginCache 集合中保存
export function getPluginContext(plugin: Plugin,pluginCache: Record<string, SerializablePluginCache> | void,graph: Graph,options: NormalizedInputOptions,fileEmitter: FileEmitter,existingPluginNames: Set<string>
): PluginContext {let cacheable = true;if (typeof plugin.cacheKey !== 'string') {if ( // 插件没写 name 不缓存plugin.name.startsWith(ANONYMOUS_PLUGIN_PREFIX) ||plugin.name.startsWith(ANONYMOUS_OUTPUT_PLUGIN_PREFIX) ||existingPluginNames.has(plugin.name)) {cacheable = false;} else {existingPluginNames.add(plugin.name);}}let cacheInstance: PluginCache;if (!pluginCache) {cacheInstance = NO_CACHE;} else if (cacheable) {// 根据插件传递的配置设置缓存 keyconst cacheKey = plugin.cacheKey || plugin.name;cacheInstance = createPluginCache( // 封装操作 cache 缓存的操作(get、has、set、delete)// 在创建时已经根据 key 分配了对象pluginCache[cacheKey] || (pluginCache[cacheKey] = Object.create(null)));} else {cacheInstance = getCacheForUncacheablePlugin(plugin.name);}// 返回给开发者可以调用的方法、属性return {addWatchFile(id) {if (graph.phase >= BuildPhase.GENERATE) {return this.error(errorInvalidRollupPhaseForAddWatchFile());}graph.watchFiles[id] = true;},cache: cacheInstance,// ...};
}// 记录缓存操作
export function createPluginCache(cache: SerializablePluginCache): PluginCache {return {delete(id: string) {return delete cache[id];},get(id: string) {const item = cache[id];if (!item) return;item[0] = 0;return item[1];},has(id: string) {const item = cache[id];if (!item) return false;item[0] = 0;return true;},set(id: string, value: any) {cache[id] = [0, value];}};
}

插件中使用缓存

  • 插件 cache 的内容都会放在 Graph 的 pluginCache 中,在分配缓存时已经根据插件的 key 进行了设置,所以在插件中可以直接 this.cache 进行使用而不必担心和其它插件的缓存冲突
{name: "test-plugin",buildStart() {if (!this.cache.has("cache")) {this.cache.set("cache", "cache something");} else {// 第二次执行rollup的时候会执行console.log(this.cache.get("cache"));}},
}

可替换的 replace pluginContext

  • pluginContext 会根据不同的 hook,动态增加属性、方法,比如 transform hook
  • 在通过 pluginDriver.hookReduceArg0 调用 transform hook时,第四个参数即是替换后的 pluginContext
		code = await pluginDriver.hookReduceArg0('transform',[currentSource, id],transformReducer,(pluginContext, plugin): TransformPluginContext => { pluginName = plugin.name;return {...pluginContext, // 在原来 context 的基础上再添加额外的属性addWatchFile(id: string) {transformDependencies.push(id); // 收集插件中通过 this.addWatchFile 添加的文件 idpluginContext.addWatchFile(id);},cache: customTransformCache? pluginContext.cache: getTrackedPluginCache(pluginContext.cache, useCustomTransformCache),};});

PluginDriver 提供 asyn、first、parallel 等类型 hook

  • rollup 根据不同场景提供了不同类型的 hook
    • async:该钩子也可以返回一个解析为相同类型的值的 Promise;否则,该钩子被标记为 sync。
    • first:如果有多个插件实现此钩子,则钩子按顺序运行,直到钩子返回一个不是 null 或 undefined 的值。
    • sequential:如果有多个插件实现此钩子,则所有这些钩子将按指定的插件顺序运行。如果钩子是 async,则此类后续钩子将等待当前钩子解决后再运行。
    • parallel:如果有多个插件实现此钩子,则所有这些钩子将按指定的插件顺序运行。如果钩子是 async,则此类后续钩子将并行运行,而不是等待当前钩子。
export class PluginDriver {// ...hookFirstSync<H extends SyncPluginHooks & FirstPluginHooks>(hookName: H,parameters: Parameters<FunctionPluginHooks[H]>,replaceContext?: ReplaceContext): ReturnType<FunctionPluginHooks[H]> | null {// ...}async hookParallel<H extends AsyncPluginHooks & ParallelPluginHooks>(hookName: H,parameters: Parameters<FunctionPluginHooks[H]>,replaceContext?: ReplaceContext): Promise<void> {// ...}// ...
}

getSortedPlugins 运行时收集并存储插件对应 hook

  • Rollup 通过 getSortedPlugins 对插件的对应 hook 进行排序后收集在 this.sortedPlugins 集合中存储
  • 根据 pre、normal、post 顺序排序每个hook
// 抽取插件中有对应 hookName 的插件
private getSortedPlugins( hookName: keyof FunctionPluginHooks | AddonHooks,validateHandler?: (handler: unknown, hookName: string, plugin: Plugin) => void
): Plugin[] {return getOrCreate( // 根据 hookName 抽取所有符合的插件,运行时收集对应 hook 的插件放进 this.sortedPlugins 里this.sortedPlugins,hookName,() => getSortedValidatedPlugins(hookName, this.plugins, validateHandler) // 抽取插件中有对应 hookName 的插件);
}export function getOrCreate<K, V>(map: Map<K, V>, key: K, init: () => V): V {const existing = map.get(key);if (existing !== undefined) {return existing;}const value = init();map.set(key, value);return value;
}export function getSortedValidatedPlugins(hookName: keyof FunctionPluginHooks | AddonHooks,plugins: readonly Plugin[],validateHandler = validateFunctionPluginHandler
): Plugin[] {const pre: Plugin[] = [];const normal: Plugin[] = [];const post: Plugin[] = [];// 遍历所有插件,根据指定hook(options、transform、...)提取插件for (const plugin of plugins) {const hook = plugin[hookName];if (hook) {if (typeof hook === 'object') {validateHandler(hook.handler, hookName, plugin);if (hook.order === 'pre') {pre.push(plugin);continue;}if (hook.order === 'post') {post.push(plugin);continue;}} else {validateHandler(hook, hookName, plugin);}normal.push(plugin);}}// 根据 pre、normal、post 顺序排序每个hookreturn [...pre, ...normal, ...post];
}

sync hook

  • 同步执行 hook,返回第一个非 null 的结果
	// chains synchronously, first non-null result stops and returnshookFirstSync<H extends SyncPluginHooks & FirstPluginHooks>(hookName: H,parameters: Parameters<FunctionPluginHooks[H]>,replaceContext?: ReplaceContext): ReturnType<FunctionPluginHooks[H]> | null {for (const plugin of this.getSortedPlugins(hookName)) {const result = this.runHookSync(hookName, parameters, plugin, replaceContext);if (result != null) return result;}return null;}

parallel hook

  • 用于并行执行的 hook,忽略返回值
  • 通过 Promise.all 并行执行
	async hookParallel<H extends AsyncPluginHooks & ParallelPluginHooks>(hookName: H,parameters: Parameters<FunctionPluginHooks[H]>,replaceContext?: ReplaceContext): Promise<void> {const parallelPromises: Promise<unknown>[] = [];for (const plugin of this.getSortedPlugins(hookName)) { // getSortedPlugins 根据 hookName 提取对应的插件if ((plugin[hookName] as { sequential?: boolean }).sequential) { // 非顺序执行就先存起来然后并行执行await Promise.all(parallelPromises);parallelPromises.length = 0;await this.runHook(hookName, parameters, plugin, replaceContext);} else {parallelPromises.push(this.runHook(hookName, parameters, plugin, replaceContext)); // 将调用过程放进 Promise.then 任务中,等待 parallelPromises.push 同步任务收集完成后执行}}await Promise.all(parallelPromises); // 并行执行所有收集到的 runHook }

this.runHookSync

  • 同步调用时,通过 this.pluginContexts.get(plugin) 获取到插件上下文供插件开发者使用
	private runHookSync<H extends SyncPluginHooks>(hookName: H,parameters: Parameters<FunctionPluginHooks[H]>,plugin: Plugin,replaceContext?: ReplaceContext): ReturnType<FunctionPluginHooks[H]> {const hook = plugin[hookName]!;const handler = typeof hook === 'object' ? hook.handler : hook;let context = this.pluginContexts.get(plugin)!;if (replaceContext) {context = replaceContext(context, plugin);}try {// eslint-disable-next-line @typescript-eslint/ban-typesreturn (handler as Function).apply(context, parameters);} catch (error_: any) {return error(errorPluginError(error_, plugin.name, { hook: hookName }));}}

this.runHook

  • 异步调用时,如果是结果也是 Promise,会暂存然后等待所有Promise都执行结束
	private runHook<H extends AsyncPluginHooks | AddonHooks>(hookName: H,parameters: unknown[],plugin: Plugin,replaceContext?: ReplaceContext | null): Promise<unknown> {// We always filter for plugins that support the hook before running itconst hook = plugin[hookName];const handler = typeof hook === 'object' ? hook.handler : hook;let context = this.pluginContexts.get(plugin)!; // 获取插件的上下文,上下文通过 PluginDriver 封装了一系列和 graph 等相关的方法if (replaceContext) { //transform 钩子需要往 plugin 上下文中添加额外的内容context = replaceContext(context, plugin);}let action: [string, string, Parameters<any>] | null = null;return Promise.resolve().then(() => {if (typeof handler !== 'function') {return handler;}const hookResult = (handler as Function).apply(context, parameters); // 执行插件对应的 hookName 钩子if (!hookResult?.then) {return hookResult;}action = [plugin.name, hookName, parameters]; // 如果钩子返回 Promise 存储对应操作this.unfulfilledActions.add(action);return Promise.resolve(hookResult).then(result => { // action was fulfilledthis.unfulfilledActions.delete(action!); // 钩子返回 Promise 完成清除对应未 fullfilled 的操作return result;});}).catch(error_ => {if (action !== null) {this.unfulfilledActions.delete(action);}return error(errorPluginError(error_, plugin.name, { hook: hookName }));});}

和 webpack 插件系统区别

  • Rollup 通过抽象化一个 PluginDriver 的实例负责专门驱动插件的调用,并且 PluginDriver 和 Graph 绑定,能够共享打包过程的信息;webpack 通过 tapable 进行订阅发布,本身可以脱离 webpack 使用
  • 在运行模式上,Rollup 是运行时根据 hookName 收集对应的插件 ,然后对插件进行排序后存储,通过 runHook 或 runHookSync 进行调用;webpack 通过订阅发布,先注册插件,然后在生命周期的流程中调用。总的来说 Rollup 的运行时收集比起 webpack 具有一点点内存优势
http://www.yayakq.cn/news/513317/

相关文章:

  • 台州营销型网站建设做外贸的怎么建立自己的网站
  • 唐山培训网站建设网站开发维护协议
  • 简单网站建设报价单珠海市城乡住房建设局网站
  • 如何用腾讯云主机做网站兰州模板网站seo价格
  • 织梦网站添加广告位东阳网站建设软件开发
  • 做网站流量是什么vultr服务器建wordpress
  • 织梦网站模板如何安装教程视频网站安全建设 需求分析
  • 网站建设佰金手指科杰二八中小企业有哪些公司名单
  • 长沙网站开发培训温州网站优化排名
  • 电子网站模板网站抓取超时错误
  • 网站提交入口百度报名网站建设费用报价
  • 做公司的网站有哪些东西海南网
  • 太原做网站公司5大建站服务怎么运营一个微信公众号
  • 骗别人做网站浙江建站优化品牌
  • 建设银行河北分行招聘网站wordpress qq注册
  • 午夜做网站图片优化
  • 网站建设税收分类编码网站建设需要企业
  • 贵州省建设厅网站多少中级经济师考试报名
  • 网站建站行业二网站手
  • 招聘网站系统怎么做2345浏览器网页版登录
  • 莱芜企业网站建设公司带后台的html网站源码
  • wordpress tint 2.7.0无锡seo网站排名优化
  • 三大门户网站哪家做的最好淄博网站建设 很乱
  • 建设银行网站打不开宣城市市政建设集团公司网站
  • 查询企业信息的官方网站做网站寄生虫需要哪些东西
  • 深圳营销网站建设wordpress即时通讯
  • wordpress获取文章内容过滤空格昆明seo关键字推广
  • 上海专业网站建设服务网站死链怎么办
  • 建立公司网站多少钱免费男女打扑克的软件
  • 网站备案帐号做app和做网站区别