Rolldown 插件上下文 `this.error()` 完全指南:在 `onLog` 钩子中将警告升级为错误
Rolldown 插件上下文this.error()完全指南在onLog钩子中将警告升级为错误【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown导读本文围绕 RolldownRust 编写、兼容 Rollup API 的 JavaScript/TypeScript 打包器插件上下文中的this.error()方法展开重点讲解它在onLog钩子中的典型用法——把警告warning升级为错误error同时完整保留警告对象上的全部附加属性。读完本文你将掌握this.error()与this.warn()、this.info()、this.debug()等日志方法的区别理解 Rolldown 日志RolldownLog在插件层被规范化与降级/升级的处理机制并能在自己的插件中编写可复用的警告即错误策略。一、this.error()在插件上下文中的定位在 Rolldown 的插件体系中每个插件钩子执行时都能访问this即插件上下文。日志与错误相关的方法定义在 minimal-plugin-context.ts 的MinimalPluginContext接口中this.error(e: RolldownError | string): never—— 终止打包流程并抛出错误this.warn(...)—— 生成warn级别日志this.info(...)—— 生成info级别日志this.debug(...)—— 生成debug级别日志this.meta—— 插件上下文元信息rollupVersion、rolldownVersion、watchMode。而完整的PluginContext接口见 plugin-context.ts通过extends MinimalPluginContext继承了上述方法并额外提供fs、emitFile、getModuleInfo、resolve、load、parse等能力。也就是说this.error()是所有插件钩子构建期与输出期通用的基础方法。从类型签名可以确认一个关键事实error的返回类型是never意味着调用this.error()后当前执行流必然中断打包过程随之终止。这一点与this.warn()不同——警告不会中断构建只会被记录、过滤或转发给onLog处理器。二、核心用法在onLog钩子中把警告升级为错误this.error()最典型的使用场景是配合onLog钩子将某些特定警告立即升级为错误。Rolldown 文档plugin-context-error.md给出的官方示例完整如下function myPlugin() { return { name: my-plugin, onLog(level, log) { if (level warn log.code THIS_IS_NOT_OK) { return this.error(log); } }, }; }这段代码的核心语义是onLog钩子会在日志被转发给用户自定义的onLog/onwarn处理器或打印到控制台之前先接收到每一条日志level参数用于判断日志级别debug/info/warnlog是标准的RolldownLog对象其上的code、plugin、pluginCode、meta等属性是过滤的依据当命中目标警告示例中的THIS_IS_NOT_OK时直接把整个log对象传给this.error(log)。关键在于keeping all additional properties of the warning直接把警告对象透传给this.error()警告上携带的所有附加属性code、plugin、meta、loc等都会被保留在最终抛出的错误中而不是像手动throw new Error(...)那样丢失上下文信息。这样下游捕获到错误时依然能拿到完整的诊断数据。为什么是return this.error(log)this.error()的返回类型是never它必然抛出。return关键字在这里既有语义提示告诉读者此分支不会继续执行也能避免钩子继续处理该日志防止日志被重复转发。三、源码级原理error()底层如何工作MinimalPluginContextImpl中对error的实现见 minimal-plugin-context.ts只有一行public error(e: RolldownError | string): never { return error(logPluginError(normalizeLog(e), this.pluginName, { hook: this.hookName })); }其调用链可分为三步normalizeLog(e)把字符串或对象统一规范化为RolldownLog结构logPluginError(...)在 logs.ts 中实现对日志对象做错误化加工如果对象上没有pluginCode且已有的code不是字符串或不以PLUGIN_开头则把原code改名为pluginCode保留原值不丢失统一设置code PLUGIN_ERROR设置plugin为当前插件名若当前处于某个钩子中追加hook字段error(...)将RolldownLog包装为Error实例命名为RolldownError并抛出终止打包。这一点可以从接口 JSDoc 中得到印证除onLog钩子外其他钩子中抛出的插件错误都会被附加code: PLUGIN_ERROR与plugin: plugin.name如果传入的code已存在且不以PLUGIN_开头则会被改名为pluginCode。这也解释了为何在onLog中传入的警告如THIS_IS_NOT_OK最终会同时拥有pluginCode: THIS_IS_NOT_OK与code: PLUGIN_ERROR两个字段——原始标识被完整保留只是被升级为错误码体系。从 N-API 边界看插件的日志与错误方法最终都要经过 bindingify-plugin.ts 的适配层与 Rust 侧交互插件上下文由createPluginContext见 plugin-context.ts统一创建保证每个钩子调用都有独立的日志处理上下文。四、this.error()与 warn / info / debug 的对比同一文件 minimal-plugin-context.ts 中可以看到四个日志方法在实现层的高度一致性它们都经由getLogHandler创建只是级别与默认code不同方法级别默认code是否中断构建在logLevel: silent下的行为this.error()错误PLUGIN_ERROR是never仍然抛出错误无法被静默this.warn()warnPLUGIN_WARNING否不做任何事见 plugin-context-warn.mdthis.info()infoPLUGIN_LOG否不做任何事logLevel为warn或silent时见 plugin-context-info.mdthis.debug()debugPLUGIN_LOG否不做任何事对照实现代码可以确认this.debug getLogHandler(LOG_LEVEL_DEBUG, PLUGIN_LOG, onLog, pluginName, logLevel); this.info getLogHandler(LOG_LEVEL_INFO, PLUGIN_LOG, onLog, pluginName, logLevel); this.warn getLogHandler(LOG_LEVEL_WARN, PLUGIN_WARNING, onLog, pluginName, logLevel);也就是说this.warn()生成的警告会得到code: PLUGIN_WARNING而this.error()抛出的是code: PLUGIN_ERROR。两者都遵循PLUGIN_前缀的错误码规范方便用户在onLog中统一过滤。关于meta与pluginCode的补充plugin-context-warn.md 中特别提到如果日志对象带code但还没有pluginCode则code会被改名为pluginCode因为插件警告总会由 Rolldown 附加PLUGIN_WARNING。这一规则与this.error()的logPluginError加工逻辑完全同源体现了 Rolldown 在日志处理上的统一设计原始代码标识pluginCode永远被保留系统级 code 由 Rolldown 统一管理。五、onLog钩子中的日志流与防循环机制在onLog钩子中调用this.error()或this.warn()、this.info()之所以安全是因为 Rolldown 对日志回传做了防循环约束。plugin-hooks-onlog.md 明确了三点行为与其他会为日志附加插件名的钩子不同onLog不会修改日志的属性由onLog钩子产生的日志不会再回传给同一插件的onLog钩子如果另一个插件在自己的onLog中响应式地产生了新日志这条日志也不会再回传给原始的onLog钩子。因此把警告升级为错误不会造成无限递归。文档中的完整示例展示了多插件场景下的日志流转原样整理如下function plugin1() { return { name: plugin1, buildStart() { this.info({ message: Hey, pluginCode: SPECIAL_CODE }); }, onLog(level, log) { if (log.plugin plugin1 log.pluginCode SPECIAL_CODE) { // We turn logs into warnings based on their code. This warnings // will not be passed back to the same plugin to avoid an // infinite loop, but other plugins will still receive it. this.warn(log); return false; } }, }; } function plugin2() { return { name: plugin2, onLog(level, log) { if (log.plugin plugin1 log.pluginCode SPECIAL_CODE) { // You can modify logs in this hooks as well log.meta processed by plugin 2; // This turns the log back to info. If this happens in // response to the first plugin, it will not be passed back to // either plugin to avoid an infinite loop. If both plugins are // active, the log will be an info log if the second plugin is // placed after the first one this.info(log); return false; } }, }; }这个示例至少揭示了三个可在自己插件中直接复用的模式日志可被就地修改onLog中可以直接给log对象追加meta等字段再通过this.info(log)/this.warn(log)重新投递返回false可吞掉日志钩子返回false表示该日志处理完毕不再继续向下游转发级别可在日志链中变化info → warn → info的传递链中最终呈现的级别取决于各插件的处理顺序。把这种模式与this.error(log)结合你可以实现特定插件代码的警告直接升级为错误的通用策略在onLog中判断log.pluginCode或log.code命中即this.error(log)未命中则return false或放行。六、与其他日志入口的关系onLog/onwarn/logLevelthis.error()在onLog中触发的警告即错误机制处于 Rolldown 日志处理链的最前端。整条链路大致为插件或 Rolldown 内部产生日志先进入各插件的onLog钩子可修改、吞掉或升级为错误未被拦截的日志继续转发给用户通过InputOptions配置的自定义onLog/onwarn处理器最终决定是否打印到控制台时还会参考logLevel配置debug/info/warn/silent。这意味着如果你希望只在特定构建中启用警告即错误可以在onLog钩子内部通过环境变量、选项或this.meta判断后再决定是否调用this.error()若logLevel被设为silentthis.warn()/this.info()会静默参见 plugin-context-warn.md 与 plugin-context-info.md但this.error()依然会抛出——错误不应被静默吞掉这是插件作者需要牢记的边界onwarn与onLog的过滤器相关实现位于 get-log-filter.ts插件日志与内置日志走同一套过滤管道。七、实践建议写出可靠的警告即错误插件结合本文所述机制推荐以下落地要点优先用pluginCode过滤由于 Rolldown 会把非PLUGIN_前缀的code自动改名到pluginCode在onLog中同时检查log.code与log.pluginCode可以覆盖更多来源的日志官方建议插件日志尽量携带pluginCode以便用户过滤。透传整个 log 对象升级错误时直接this.error(log)而不是只传 message从而保住loc、meta、id、hook等诊断上下文。不要担心无限循环onLog产生的日志不会回传给同一插件升级为错误后构建立即终止链路天然收敛。控制错误粒度只对确定不可容忍的code升级其余警告用this.warn(log)转发或return false吞掉避免把构建变成一警告就失败的脆皮模式。善用懒计算如果日志内容需要昂贵计算才能生成请使用函数形式this.warn(() ...)确保仅在日志确实会被处理时才执行计算参见 plugin-context-warn.md 中的提示。小结this.error()是 Rolldown 插件上下文中最重的日志方法它终止构建、抛出RolldownError并在底层通过logPluginErrorlogs.ts把插件信息、钩子信息与原始code完整并入错误对象。把它与onLog钩子结合即可在保持警告全部附加属性的前提下把特定警告升级为致命错误——这是实现 CI 严格检查、编码规范门禁、以及自定义 lint 策略时最直接有效的插件手段。如需进一步了解onLog的完整语义可继续阅读 plugin-hooks-onlog.md相关 API 类型定义集中在 minimal-plugin-context.ts 与 plugin-context.ts。【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考