Rolldown 混合导出警告(MIXED_EXPORTS)排查与修复:默认导出与命名导出并存时的 CommonJS 兼容指南

发布时间:2026/9/15 18:43:25
Rolldown 混合导出警告(MIXED_EXPORTS)排查与修复:默认导出与命名导出并存时的 CommonJS 兼容指南 Rolldown 混合导出警告MIXED_EXPORTS排查与修复默认导出与命名导出并存时的 CommonJS 兼容指南【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown当你的库入口同时导出default与命名导出时Rolldown 会触发MIXED_EXPORTS警告提醒你这种写法会给 CommonJS 消费者带来使用成本。本文以packages/rolldown/src/options/docs/checks-mixed-exports.md为骨架结合源码中的导出模式判定逻辑、诊断事件实现与配置校验链路讲解警告的触发条件、CommonJS 消费差异、两种修复方案以及checks.mixedExports与output.exports的底层关系。读完你将能准确理解并消除这类警告同时掌握导出模式auto/default/named/none对包 API 设计的实际影响。什么会触发这条警告当同一个入口模块既存在default导出、又存在命名导出时Rolldown 就会在非 ESM 输出格式下发出MIXED_EXPORTS警告。原文档给出了最小复现示例// main.js export default function greet() { return Hello; } export const version 1.0.0;这里的main.js同时使用了默认导出export default和命名导出export const version。在 CommonJS 环境中消费该产物时默认导出不会直接映射为module.exports而是挂在.default属性上导致调用方式不直观。该警告对应的诊断事件定义在 crates/rolldown_error/src/build_diagnostic/events/mixed_exports.rs其中记录了触发警告的module_id、module_name、entry_module与具体的export_keys其生成的完整消息为Entry module ... is using named (including version) and default exports together. Consumers of your bundle will have to usemain.defaultto access the default export, which may not be what you want. Useoutput.exports: namedto disable this warning.为什么是问题CommonJS 消费者的访问差异警告的本质是导出模式在 CommonJS 环境下的语义差异。假设上面的模块被打包为 CommonJS 输出消费者通过require使用时// CommonJS consumer const myLib require(my-lib); myLib.default(); // 需要额外通过 .default 访问默认导出 myLib.version; // 命名导出可以直接访问也就是说命名导出可以直接通过require的返回值访问而默认导出必须经过.default这一层间接访问。如果库的入口设计是整体导出为一个函数即require(my-lib)直接得到可调用对象这种混用导出会让消费者困惑——他们拿到的不是函数而是一个包含default属性的对象。packages/rolldown/src/options/docs/output-exports.md对这个问题有更完整的说明若入口只有单个默认导出require(your-lib)返回的就是默认导出本身若采用named模式且同时存在默认导出require(your-lib)返回的是{ default: ..., bar: ... }这样的命名空间对象。对于既能被 ESM 工具链解析、又能被 CommonJS 直接 require的库多数工具默认会把 ESM 命名空间作为 require 的返回值因此默认导出永远落在.default上此时唯一稳妥的接口设计就是全部使用命名导出named模式。修复方案原文档给出了两种修复思路可按库的 API 定位选择。方案一只使用命名导出如果默认导出本身就是为 CommonJS 消费者提供直接调用的便捷入口最干净的做法是移除export default将默认函数改为具名函数// Option 1: Use only named exports export function greet() { return Hello; } export const version 1.0.0;这样require(my-lib)返回{ greet, version }消费者直接myLib.greet()即可无需关心.default。方案二显式声明 output.exports 为 named如果确实需要保留默认导出例如为了 ESM 场景下import lib from my-lib的体验则可以通过配置显式承认这种导出形态从而消除警告// Option 2: Configure output.exports export default { output: { exports: named, // Suppress the warning }, };需要注意output.exports: named只是承认默认导出以.default形式存在于命名空间对象中并不会移除默认导出本身。它改变的是 Rolldown 对导出模式的判定结果进而抑制该警告。源码视角警告是在哪里、如何产生的触发链路determine_export_mode警告的产生逻辑集中在 crates/rolldown/src/utils/chunk/determine_export_mode.rs 的determine_export_mode函数中该函数注释标明是从 Rollup 的getExportMode.ts移植而来。其核心分支如下OutputExports::Named直接返回Named不做检查OutputExports::Default仅当导出名恰好只有一个且为default时合法否则抛出invalid_export_option错误OutputExports::None仅当没有导出时合法否则同样报错OutputExports::Auto默认值先按导出集合自动推断——无导出为None仅单个default为Default其余为Named如果推断结果是Named、输出格式不是 ESM、且导出集合中包含default就会向warnings队列 push 一条mixed_export警告然后再返回Named。这段逻辑说明了一个关键事实警告只在非 ESM 输出格式如 CommonJS / IIFE / UMD下触发。纯 ESM 输出没有.default兼容问题因此不会告警。同时只要显式指定了output.exports非auto就会绕过Auto分支警告自然也不会产生。诊断事件的组装与编号mixed_export构造函数位于 crates/rolldown_error/src/build_diagnostic/constructors.rs它接收module_id、module_name、entry_module和export_keys构造出MixedExports事件源码中通过.with_severity_warning()标记为 warning 级别。该事件在 crates/rolldown_error/src/types/event_kind.rs 中编号为MixedExports 11其字符串标识为MIXED_EXPORTS见同文件 event_kind.rs在 crates/rolldown_error/src/generated/event_kind_switcher.rs 中以位掩码1 11参与诊断开关控制。通过 checks.mixedExports 控制警告开关MIXED_EXPORTS属于 Rolldown 的checks系列可选诊断可以通过checks.mixedExports独立控制开关。配置项定义与默认值JS 侧类型定义见 packages/rolldown/src/options/generated/checks-options.ts为mixedExports?: boolean校验与描述定义在 packages/rolldown/src/utils/validator.ts描述为Whether to emit warnings when the way to export values is ambiguous导出方式存在歧义时是否发出警告Rust 侧开关装配位于 crates/rolldown_common/src/generated/checks_options.rsflag.set(EventKindSwitcher::MixedExports, value.mixed_exports.unwrap_or(true))。从unwrap_or(true)可以确认该警告默认开启无需任何配置即可收到提示。如果确认混用导出是刻意的 API 设计可以在配置中显式关闭export default { checks: { mixedExports: false, // 关闭 MIXED_EXPORTS 警告 }, output: { exports: named, }, };CLI 方式checks.mixedExports同样暴露为命令行选项。packages/rolldown/tests/cli/__snapshots__/cli-e2e.test.ts.snap中的 CLI 帮助信息快照显示其形式为--checks.mixedExports Whether to emit warnings when the way to export values is ambiguous.因此在命令行构建时可以通过--checks.mixedExports false或--no-checks.mixedExports风格的布尔写法关闭该诊断。与原文档其他主题的关联output.exports 详解完整的auto/default/named/none四种模式及其在 CommonJS 消费者侧的差异示例见 packages/rolldown/src/options/docs/output-exports.md建议与本文对照阅读on-warn / log-levelMIXED_EXPORTS属于 warning 级别诊断可通过logLevel调整整体日志门槛或通过onLog钩子按事件码MIXED_EXPORTS做自定义处理其他 checks 系列checks目录下还有checks-eval.md、checks-circular-dependency.md、checks-import-is-undefined.md等同系列文档它们共享同一套开关与事件编号机制。小结MIXED_EXPORTS警告的本质是提醒你入口模块的导出形态在 CommonJS 消费场景下存在歧义默认导出会被迫退化为.default属性。修复时优先考虑只用命名导出以保持接口直观必须保留默认导出时显式设置output.exports: named或在配置/CLI 中关闭checks.mixedExports即可。从源码看这条警告由determine_export_mode在auto模式、非 ESM 格式且导出集合含default时生成事件码为MIXED_EXPORTS默认开启属于可按位独立控制的 checks 类诊断非常适合在大型库工程中做精细化治理。【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考