ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Rolldown onLog 选项完全指南:拦截、过滤与升级构建日志的实战方案

Rolldown onLog 选项完全指南:拦截、过滤与升级构建日志的实战方案 Rolldown onLog 选项完全指南拦截、过滤与升级构建日志的实战方案【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldownonLog是 Rolldown面向 JavaScript/TypeScript 的 Rust 高速打包器API 兼容 Rollup在InputOptions中提供的日志拦截钩子它允许你在构建期间对每一条日志debug/info/warn进行过滤、改写、重新定级甚至将警告升级为致命错误。本文以 on-log.md 文档为核心结合 input-options.ts、logger.ts 与 logging.ts 等源码完整讲解onLog的签名、执行时机、与logLevel的联动机制以及默认处理器default handler的用法帮助你精确控制构建输出并把忽略循环依赖警告把警告升级为错误等场景落到可运行的配置上。一、onLog 是什么在日志抵达控制台之前的最后一道关卡在 Rolldown 的构建管线中无论是核心 bundler 产生的日志还是插件通过this.warn/this.info/this.debug发出的日志最终都会汇聚到一个统一的日志处理器上。onLog选项就是在这个汇聚点上插入的用户自定义函数它的类型定义位于 input-options.tsexport type OnLogFunction ( level: LogLevel, log: RolldownLog, defaultHandler: LogOrStringHandler, ) void;其中level是日志级别取值为info | debug | warn类型见 logging.tslog是结构化的RolldownLog对象见下文第四节包含message、code、plugin、loc、frame等字段defaultHandler是内置的默认处理器调用它决定这条日志的最终去向打印到控制台、以另一个级别重新处理或升级为抛出的错误。在 input-options.ts 中onLog的官方 JSDoc 给出了它的定位A function that intercepts log messages. If not supplied, logs are printed to the console.拦截日志消息的函数若不提供日志将直接打印到控制台。这意味着onLog是你在日志被打印之前唯一能系统性地介入所有日志的地方。二、与 logLevel 的联动被过滤掉的日志根本不会到达 onLog原文档第一条规则是This handler will not be invoked if logs are filtered out by thelogLeveloption. I.e. by default,debuglogs will be swallowed.即onLog处理器不会被logLevel过滤掉的日志触发。logLevel选项默认值为info见 input-options.ts控制构建日志的详细程度其取值类型LogLevelOption LogLevel | silent即info | debug | warn | silent定义在 logging.ts。级别之间的吞掉关系由优先级表决定logging.ts级别优先级值说明debug0最低优先级info1默认级别warn2警告silent3不输出任何日志结合 log-level.md 的说明默认的logLevel: info意味着info和warn级别的日志会被处理而debug日志会被吞掉swallowed——它们既不会被传给插件的onLoghook也不会被传给onLog选项更不会打印到控制台。底层实现印证了这一规则。在 logger.ts 的getLogger中每一条日志进入时都会先做一次优先级比对const minimalPriority logLevelPriority[logLevel]; const logger (level, log, skipped new Set()) { const logPriority logLevelPriority[level]; if (logPriority minimalPriority) { return; // 低于最低允许级别直接丢弃 } // ... 后续依次调用插件 onLog hook 与用户 onLog 选项 };也就是说过滤发生在任何 handler 被调用之前。如果你希望debug日志也能被onLog捕获处理必须同时把logLevel设为debug例如export default defineConfig({ logLevel: debug, onLog(level, log, defaultHandler) { console.log([custom logger], level, log.code); defaultHandler(level, log); }, });三、defaultHandler打印、改级与升级为错误的核心机制原文档第二条规则是If the default handler is not invoked, the log will not be printed to the console. Moreover, you can change the log level by invoking the default handler with a different level. Using the additional levelerrorwill turn the log into a thrown error that has all properties of the log attached.这条规则包含三个层层递进的能力不调用 defaultHandler 就不打印只要你的onLog中不调用第三个参数defaultHandler这条日志就不会出现在控制台。这是实现忽略特定日志的最直接方式。可以用不同级别重新调用 defaultHandler比如把一条warn重新以info级别处理实现降级或反过来把info升级为warn。使用额外的error级别可以让日志变成抛出的错误defaultHandler的签名是LogOrStringHandler (level: LogLevelWithError, log: RolldownLogWithString) voidlogging.ts其中LogLevelWithError LogLevel | error。当你以error级别调用它时日志会被转换成一个RolldownError并抛出——该错误携带日志对象的全部属性message、code、plugin、loc、frame等因此你可以在catch中通过error.code等方式精确定位失败原因。这段逻辑在 logger.ts 的getOnLog中有对应的实现if (onLog) { const minimalPriority logLevelPriority[logLevel]; return (level, log) onLog(level, addLogToString(log), (level, handledLog) { if (level LOG_LEVEL_ERROR) { return error(normalizeLog(handledLog)); // error 级别抛出错误 } if (logLevelPriority[level] minimalPriority) { defaultOnLog(level, normalizeLog(handledLog)); // 否则按新级别走默认处理 } }); } return defaultOnLog;值得注意的是当onLog选项存在时传入 handler 的log对象还会被addLogToString附加一个自定义的toString方法logger.ts其输出会拼接插件名、文件位置file:line:column与消息本身便于直接String(log)或console.log(log)时得到可读文本。默认打印逻辑defaultPrintLoglogger.ts分别用console.warn/console.debug/console.info输出warn/debug/ 其余级别。四、RolldownLog 对象结构onLog 里你能拿到什么onLog第二个参数是结构化的RolldownLog其字段定义于 logging.ts。常用的核心字段包括字段含义示例message日志正文必填foo is imported by barcode日志代码可用于精确匹配CIRCULAR_DEPENDENCY、PLUGIN_ERRORplugin产生日志的插件名plugin1pluginCode插件自定义代码SPECIAL_CODEid/ids关联的模块 id 列表/src/main.jsloc源码位置{ file, line, column }{ file: /src/a.js, line: 1, column: 0 }frame源码上下文片段 1 | export ...pos字符偏移量123url相关文档链接官方文档地址stack错误堆栈错误场景调用栈文本需要注意的是字符串形式的日志会被normalizeLog归一化为{ message: log }log-handler.ts所以defaultHandler(warn, some message)这种字符串入参也是合法的。五、完整实战示例5.1 忽略特定代码的日志静默处理以 input-options.ts 中的官方示例为蓝本忽略所有CIRCULAR_DEPENDENCY警告其余警告升级为错误、其他级别照常打印import { defineConfig } from rolldown; export default defineConfig({ onLog(level, log, defaultHandler) { if (log.code CIRCULAR_DEPENDENCY) { return; // 不调用 defaultHandler → 该日志不会打印到控制台 } if (level warn) { defaultHandler(error, log); // 把其他警告变成抛出的错误 } else { defaultHandler(level, log); // 其余日志按原级别打印 } }, });在这个例子中return语句不调用 defaultHandler对应原文档不调用默认处理器则日志不打印的规则defaultHandler(error, log)对应以error级别调用会把日志变成抛出的错误的规则抛出的错误携带log的全部属性code、plugin、loc等因此 CI 中可以直接catch (e) { if (e.code ...) }来做分类处理。5.2 只关心 warnings其余透传如果你只想接管warn级别的日志同时保持其他级别默认行为export default defineConfig({ onLog(level, log, defaultHandler) { if (level warn) { // 例如把某类警告静音其他警告打印 if (log.code UNUSED_EXTERNAL) return; } defaultHandler(level, log); }, });5.3 降级与自定义过滤规则你可以利用logLevelPrioritylogging.ts的语义做更细粒度的处理。例如只允许打印warn及以上、把info降级为debugexport default defineConfig({ onLog(level, log, defaultHandler) { if (level info) { defaultHandler(debug, log); // 降级配合 logLevel: debug 才会输出 } else { defaultHandler(level, log); } }, });注意defaultHandler内部仍会以logLevel作为最低门槛做二次校验见上文getOnLog源码中的logLevelPriority[level] minimalPriority判断所以即使你在 handler 中升级了一条日志最终是否打印依然受logLevel约束——被logLevel过滤掉的日志从一开始就不会进入onLog。六、从 onwarn 迁移onLog 是它的正式替代品Rolldown 保留了兼容 Rollup 的onwarn选项但已标记为deprecated见 input-options.tsThis is a legacy API. Consider usingonLoginstead for better control over all log types.两者的行为关系定义在 on-warn.mdIf both anonLogandonwarnhandler are provided, theonwarnhandler will only be invoked ifonLogcalls its default handler with alevelofwarn.也就是说当两者同时存在时onLog拥有更高优先级只有当onLog以warn级别调用defaultHandler时onwarn才会被触发。这一行为在 logger.ts 的getDefaultOnLog中有直接体现——只有level LOG_LEVEL_WARN的日志才会路由到onwarn其余级别直接走printLog。on-warn-deprecation.md 给出了标准的迁移对照onwarn的忽略某类警告 其余按默认处理// 迁移前使用 onwarn export default { onwarn(warning, defaultHandler) { if (warning.code CIRCULAR_DEPENDENCY) return; defaultHandler(warning); }, };等价迁移为onLog后// 迁移后使用 onLog export default { onLog(level, log, defaultHandler) { if (level warn) { // 仅处理警告级别与 onwarn 行为一致 if (log.code CIRCULAR_DEPENDENCY) return; defaultHandler(level, log); } else { defaultHandler(level, log); // 其他级别透传 } }, };迁移要点onLog比onwarn多了level参数因此你需要显式判断level warn来复刻原onwarn只处理警告的语义作为回报你获得了对debug/info日志的统一治理能力。七、与插件 onLog hook 的关系完整的调用链onLog选项并不是日志处理链的唯一入口——插件同样可以声明onLoghook。完整的链路顺序定义在 logger.ts 的getLogger中日志先按logLevel过滤低于最低优先级直接返回依次调用所有插件的onLoghook按getSortedPlugins排序每个 hook 都可以调用this.info/this.warn/this.debug重新投递日志这些回调会通过skipped集合防止同一插件的无限循环若某个插件 hook 返回false日志在此中断所有插件 hook 处理完毕后才落到用户配置的onLog选项getOnLog的产物。关于插件 hook 侧的细节plugin-hooks-onlog.md 补充了两条重要边界其一与其它 hook 不同onLoghook 不会给日志附加或修改属性如自动加上插件名其二由某个插件的onLoghook 产生的日志不会回传给该插件自身若另一个插件针对它再次产生日志也不会传回给最初的那个插件以此避免无限递归。此外插件通过this.info({ message: Hey, pluginCode: SPECIAL_CODE })发出的日志会携带plugin与pluginCode字段见 log-handler.ts 的getLogHandler自动填充log.plugin pluginName与log.code codeonLog选项里可以据此精确识别哪条日志来自哪个插件。因此如果你的目标是全局统一治理所有日志用onLog选项如果目标是某个插件内部对自身日志做二次处理用插件的onLoghook。两者可以在同一构建中并存并按上述顺序协作。八、实践建议与边界提示logLevel: silent会关闭一切当logLevel为silent优先级 3时所有低于它的日志包括warn都不会进入onLog。想让onLog完全接管输出可以显式设置logLevel: debug以放开全部级别再在 handler 内自行过滤。error级别会中断构建把日志升级为error意味着构建流程立即抛出异常适合CI 中把警告当作失败的场景例如配合process.env.CI条件开关。不要漏掉defaultHandler一旦你提供了onLog就承担了是否打印、如何打印的全部责任——忘记对某类日志调用defaultHandler会导致它们被静默吞掉排查时容易困惑。日志对象是可变引用插件 hook 文档中甚至给出了在 hook 内修改log.meta的示例onLog选项收到的也是同一份对象修改会向下游传递可按需利用但也注意不要污染核心字段如code导致过滤逻辑混乱。围绕onLog仓库中还提供了配套的测试与示例可以继续深入研究相关实现集中在 packages/rolldown/src/log 目录选项定义与 JSDoc 位于 input-options.ts插件侧 hook 说明见 plugin-hooks-onlog.mdlogLevel的完整语义见 log-level.md。掌握了onLoglogLeveldefaultHandler三者组合你就拥有了对 Rolldown 构建输出的完整掌控力。【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表