Rolldown 代码分割(Code Splitting)esbuild 兼容性快照测试全景:23 个 splitting 用例深度解析

发布时间:2026/9/16 5:29:24

Rolldown 代码分割(Code Splitting)esbuild 兼容性快照测试全景:23 个 splitting 用例深度解析 Rolldown 代码分割Code Splittingesbuild 兼容性快照测试全景23 个 splitting 用例深度解析【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown导读本文以 Rolldown 仓库中 esbuild 快照差异测试的splitting类别汇总文档为核心完整梳理该类别下 23 个通过用例的测试结构与技术内涵。通过逐一映射测试夹具_config.json、源码与artifacts.snap并结合 汇总生成器 runner.ts 与codeSplitting配置项的实现源码你将掌握Rolldown 如何以 esbuild 输出为基准验证自身代码分割行为共享模块抽取、动态导入拆包、CJS/ESM 互操作、跨 chunk 循环引用等场景的期望输出长什么样以及这份汇总文档是如何被自动化生成的。一、这份汇总文档是什么esbuild 快照差异测试中的 splitting 类别Rolldown 维护了一套以 esbuild 测试用例为蓝本的快照差异snap-diff测试体系用于衡量自身打包结果与 esbuild 输出的一致性。每个 esbuild 测试类别对应一份生成式的 Markdown 汇总文档splitting.md 就是其中面向**代码分割code splitting**类别的汇总。文档结构分为四个区块# Failed Cases失败用例当前为空# Passed Cases通过用例23 个全部链接到 crates/rolldown/tests/esbuild/splitting/ 下的真实测试夹具目录# Ignored Cases忽略用例当前为空# Ignored Cases (not supported)暂不支持而忽略当前为空。也就是说在这份文档所代表的快照比较范围内splitting 类别当前是 23/23 全部通过、零失败、零忽略的状态。1.1 汇总文档的生成机制这份文档并非手写而是由 runner.ts 自动生成的。关键逻辑如下runner.ts对每个 esbuild 快照类别执行快照对比得到diffList并按用例名排序调用getSummaryMarkdownAndStats(diffList, snapCategory)生成 Markdown 与统计信息写入snap-diff/summary/类别.md即本文对应的 splitting.md汇总所有类别的 pass / failed / ignored / total 统计。在 runner.ts 中可以看到分类与排版逻辑diffList按isNotSupported→isIgnored→isFailed→ 其余为passList的顺序归类Failed区块链接到每个夹具目录下的diff.md失败差异详情Passed区块则直接链接到夹具目录本身。此外生成器对“未记录原因的跳过用例”有硬性约束凡是以.前缀跳过skipped的用例都必须在 reasons.ts 中登记进ignoreReasons、notSupportedReasons或failedReasons否则直接抛出错误提示补全文档。这意味着 splitting.md 中“无忽略、无失败”的干净状态本身就是被工具链强制审计过的结论。二、23 个通过用例全景完整列表以下完整继承汇总文档中的全部链接并统一转换为仓库根目录相对路径。每一个链接都对应 crates/rolldown/tests/esbuild/splitting/ 下一个可独立运行的测试夹具目录edge_case_issue2793_with_splittingedge_case_issue2793_without_splittingsplitting_assign_to_localsplitting_chunk_path_dir_placeholder_implicit_outbasesplitting_circular_reference_issue251splitting_cross_chunk_assignment_dependenciessplitting_cross_chunk_assignment_dependencies_recursivesplitting_duplicate_chunk_collisionsplitting_dynamic_and_not_dynamic_common_js_into_es6splitting_dynamic_and_not_dynamic_es6_into_es6splitting_dynamic_common_js_into_es6splitting_dynamic_es6_into_es6splitting_dynamic_import_issue272splitting_dynamic_import_outside_source_tree_issue264splitting_hybrid_esm_and_cjs_issue617splitting_minify_identifiers_crash_issue437splitting_missing_lazy_exportsplitting_nested_directoriessplitting_public_path_entry_namesplitting_re_export_issue273splitting_shared_common_js_into_es6splitting_shared_es6_into_es6splitting_side_effects_without_dependencies从命名与测试语义看这批用例大致覆盖以下几个主题共享模块抽取splitting_shared_es6_into_es6、splitting_shared_common_js_into_es6动态导入拆包splitting_dynamic_es6_into_es6、splitting_dynamic_common_js_into_es6以及动态/静态混用的splitting_dynamic_and_not_dynamic_es6_into_es6、splitting_dynamic_and_not_dynamic_common_js_into_es6跨 chunk 依赖splitting_cross_chunk_assignment_dependencies及其递归变体、splitting_assign_to_local、splitting_side_effects_without_dependencieschunk 命名与路径splitting_nested_directories、splitting_public_path_entry_name、splitting_chunk_path_dir_placeholder_implicit_outbase历史 issue 回归issue251循环引用、issue272动态导入、issue264源树外动态导入、issue273重导出、issue437压缩标识符崩溃、issue617ESM/CJS 混合、issue2793含/不含分割两种开关。三、测试夹具的构成与运行方式以 splitting_shared_es6_into_es6 为例一个夹具目录通常包含四类文件_config.json打包配置入口定义a.js、b.js、shared.js等输入源码artifacts.snap期望输出快照insta 快照其头部注明source: crates/rolldown_testing/src/integration_test.rs说明由集成测试框架产出部分用例还带有compile-log.txt如 splitting_missing_lazy_export等附加产物。3.1 入口配置_config.json_config.json中的config.input采用“命名入口”数组形式name决定产物 chunk 名import指向相对源码{ config: { input: [ { name: a, import: a.js }, { name: b, import: b.js } ] } }这正是 splitting_shared_es6_into_es6 的配置两个入口共享同一模块。类似地splitting_nested_directories 用pageA/page.js、pageB/page.js两个嵌套目录下的入口入口名分别命名为pageA_page、pageB_page用于验证嵌套目录场景下的 chunk 命名规则。3.2 期望输出artifacts.snap快照直接呈现打包后的可执行代码本文所有产物代码均引自对应artifacts.snap文件。例如 splitting_shared_es6_into_es6/artifacts.snap 中的输出为// a.js console.log(123); // b.js console.log(123);输入中两个入口都import { foo } from ./shared.js并console.log(foo)而shared.js中export let foo 123。快照输出显示常量foo在分割场景下被求值内联为字面量123shared.js作为共享模块被消除无需单独成 chunk这与 esbuild 在该场景下的输出基准一致。四、代表性用例源码级拆解4.1 共享模块抽取splitting_shared_es6_into_es6输入a.js、shared.js// a.js import { foo } from ./shared.js console.log(foo) // shared.js export let foo 123a.js与b.js的输入完全一致。期望快照见上文显示两个入口各自输出console.log(123)。这说明在该场景下Rolldown 既完成了共享模块的识别又通过常量传播把导出值内联进了每个入口使共享 chunk 无需单独产出——是“分割 摇树/常量折叠”协同工作的典型结果。4.2 动态导入拆包splitting_dynamic_es6_into_es6splitting_dynamic_es6_into_es6 是单个入口、动态import()的场景。其 artifacts.snap 输出两个 chunk// entry.js import(./foo.js).then(({ bar }) console.log(bar)); // foo.js let bar 123; export { bar };入口保持import()的异步形态foo.js被拆为独立异步 chunk 并补上export { bar }动态导入的bar命名导出被保留在拆出的 chunk 中。这正是codeSplitting开启时动态导入默认被拆为独立 chunk 的行为验证。4.3 CJS 与 ESM 互操作splitting_dynamic_common_js_into_es6当动态导入的目标是 CommonJS 模块、输出格式为 ESM 时需要运行时 helper 做转换。splitting_dynamic_common_js_into_es6/artifacts.snap 展示了完整形态// entry.js import(./foo.js).then((m) /* __PURE__ */ __toESM(m.default)).then(({ default: { bar } }) console.log(bar)); export { __commonJSMin as t }; // foo.js import { t as __commonJSMin } from ./entry.js; var require_foo /* __PURE__ */ __commonJSMin(((exports) { exports.bar 123; })); export default require_foo();可以看到两条关键机制其一__commonJSMin这个 CJS 包装 helper 被提升到入口 chunk并通过export { __commonJSMin as t }与import { t as __commonJSMin }在 chunk 之间共享避免重复注入同时保证模块实例唯一其二动态导入处使用__toESM(m.default)将 CJS 的default归一化为 ESM 语义。快照头部还保留// HIDDEN [\0rolldown/runtime.js]标记说明运行时模块作为隐藏依赖参与打包。4.4 跨 chunk 循环引用splitting_circular_reference_issue251splitting_circular_reference_issue251 验证循环依赖模块被分割到不同 chunk 时的正确性// a.js var q 6; // 来自 b.js var p 5; // 来自 a.js export { p, q }; // b.js import { p, q } from ./a.js; export { p, q };b.js的内容var q 6被折叠进a.jschunk而a.js再统一export { p, q }b.js只保留对a.js的转发导入。即循环引用不破坏模块初始化顺序chunk 间的 import/export 边被正确重建。4.5 跨 chunk 赋值依赖splitting_cross_chunk_assignment_dependenciessplitting_cross_chunk_assignment_dependencies/artifacts.snap 覆盖“chunk A 修改、chunk B 读取共享状态”的场景// a.js import { t as setValue } from ./shared.js; setValue(123); // b.js import ./shared.js; // shared.js var value; function getValue() { return value; } function setValue(next) { value next; } sideEffects(getValue); export { setValue as t };共享模块shared.js被抽为独立 chunka.js通过import { t as setValue }使用内部重命名的导出b.js以副作用导入方式引入同一共享 chunk。其递归变体 splitting_cross_chunk_assignment_dependencies_recursive 则进一步覆盖多层依赖链下的情形。4.6 重复 chunk 冲突消除splitting_duplicate_chunk_collisionsplitting_duplicate_chunk_collision 有 4 个入口a、b、c、da/b都导入ab.jsc/d都导入cd.js。其 artifacts.snap 表明共享模块被去重合并ab.js与cd.js各自只产出一个共享 chunk4 个入口分别引用它们。用例名中的 “collision” 指向 esbuild 测试中关于重复/冲突 chunk 的语义这里验证的是去重后不产生命名冲突。4.7 嵌套目录入口命名splitting_nested_directoriessplitting_nested_directories/artifacts.snap 输出pageA_page.js、pageB_page.js两个入口 chunk// pageA_page.js console.log(123); // pageB_page.js console.log(-123);输入中pageA/page.js与pageB/page.js各自独立无共享模块因此直接按入口名pageA_page/pageB_page产出两个独立 chunk验证了命名入口在嵌套目录下的 chunk 命名拼接规则。4.8 输出路径占位符splitting_chunk_path_dir_placeholder_implicit_outbasesplitting_chunk_path_dir_placeholder_implicit_outbase/artifacts.snap 覆盖[dir]占位符与隐式 outbase 语义// entry.js console.log(import(./file.js)); // file.js位于 output-path/should-contain/this-text/ 下 console.log(file.js);入口通过动态import(./file.js)触发拆包动态 chunk 被放置到output-path/should-contain/this-text/路径下chunk 路径的//#region注释直接记录了该虚拟输出路径验证了目录占位符按模块相对隐式 outbase 的规则展开。4.9 空模块命名空间与缺失导出splitting_missing_lazy_exportsplitting_missing_lazy_export 的 common.js 是import * as ns from ./empty.js export function foo() { return [ns, ns.missing] } export function bar() { return [ns.missing] }该用例验证对空模块做命名空间导入并访问不存在的导出ns.missing时打包输出与 esbuild 基准一致——此类“惰性导出缺失”场景不会导致崩溃或错误产物目录中的compile-log.txt记录对应编译期输出。4.10 历史 issue 回归组splitting_dynamic_import_issue272动态导入相关的历史回归splitting_dynamic_import_outside_source_tree_issue264源树之外的动态导入路径处理splitting_re_export_issue273chunk 间重导出splitting_minify_identifiers_crash_issue437开启压缩标识符minify identifiers时的崩溃回归splitting_hybrid_esm_and_cjs_issue617同一打包中 ESM 与 CJS 模块混合edge_case_issue2793_with_splitting / edge_case_issue2793_without_splitting同一边界用例在“开启/关闭分割”两种开关下的对照验证其配置均为单入口index.js。这些以issueNNN命名的用例说明该类别不仅是功能测试更是一组针对真实缺陷的回归防线——任何一次快照变化都会被 runner.ts 捕获并反映到汇总文档中。五、与公开codeSplitting选项的源码映射这批测试所验证的“代码分割开关”对应的是 Rolldown 公开 API 中的codeSplitting选项。从源码看其内部模型是 code_splitting_mode.rs 中定义的CodeSplittingMode枚举Bool(true)默认行为自动代码分割惰性加载的动态导入被拆为独立 chunk对应splitting_dynamic_es6_into_es6等场景Bool(false)关闭分割所有动态导入内联进单一 bundleAdvanced(ManualCodeSplittingOptions)开启自动分割同时携带用户定义的手动分组manual chunk grouping配置。该枚举还提供is_automatic()/is_disabled()判定方法Default实现为Bool(true)。而选项字段本身定义在 inner_bundler_options/mod.rs/// Mirrors the public codeSplitting: boolean | CodeSplittingOptions. pub code_splitting: OptionCodeSplittingMode,其注释明确说明对象形式Advanced携带的分组配置在归一化normalization阶段被拆分为“开关门gate”NormalizedBundlerOptions::manual_code_splitting。这也解释了为什么 esbuild 测试用例中无需显式配置分组仅靠默认开关即可验证自动分割行为——高级分组属于另一层归一化逻辑。六、结论与边界说明把 splitting.md 与 crates/rolldown/tests/esbuild/splitting/ 下的夹具对照可以得到如下事实该快照类别当前全部通过23 个用例全部命中Passed CasesFailed Cases、Ignored Cases、Ignored Cases (not supported)均为空覆盖维度完整共享模块抽取、动态导入拆包、CJS/ESM 互操作与运行时 helper 注入、跨 chunk 循环引用与赋值依赖、chunk 命名与路径占位符、空模块缺失导出以及多个历史 issue 回归均有对应夹具结论边界这里的“通过”指 Rolldown 的输出与 esbuild 在该类别快照基准下的期望输出一致是快照比较层面的兼容性证据该汇总文档由 runner.ts 自动生成并强制审计跳过原因是持续集成中观察代码分割行为漂移的可靠入口。对于想深入代码分割实现的读者可以从 crates/rolldown/tests/esbuild/splitting/ 的任一夹具入手配合 code_splitting_mode.rs 的选项模型以及测试框架入口 integration_test.rs快照头部标注的 source逐步展开阅读。【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/16 5:29:24

数据流式编程核心:执行单元设计原理与背压实践

我是一个平时喜欢折腾数据管线的工程师,今天想好好聊聊数据流式编程里最基础也最关键的一个概念——执行单元。这个词听起来有点学院派,但说白了,它就是数据流里那个真正干活的节点:收一条数据进来,处理一下&#xff0…

2026/9/16 5:24:24

Android架构组件实战:从MVC到MVVM的演进与核心知识点解析

做了这么多年Android开发,我越来越深刻地体会到一件事:架构组件(Android Architecture Components)真正解决的不是"代码能不能跑"的问题,而是"代码能不能长期维护"的问题。很多项目一开始写得很爽…

2026/9/16 5:24:24

Kimi砍娱乐业务押注Scaling Law:大模型能力为王

1. 一句话看明白:杨植麟到底做了个什么决定最近打开各大平台,Kimi的热度一直没下来过。从"和kimi聊天的人太多了"到"订阅会员可进入优先队列",再到开发者圈子里讨论的"kimi code怎么用""ccswitch配置kimi…

2026/9/16 6:19:26

AR-NAR混合Transformer架构原理与应用解析

我无法根据当前输入生成符合要求的博文。原因如下:项目标题为“YuE”,但未提供任何实质性内容:项目正文为空、关键词为空、摘要描述为空。所谓“相关热搜词”和“最新网络热词”虽列出了大量Python、Hugging Face等泛化词汇,但无一…

2026/9/16 6:19:26

STM32嵌入式AI编程:从寄存器语义建模到量产闭环验证

1. 这不是“AI写代码”,而是嵌入式工程师的新型工作流重构我第一次把Claude Code接入STM32项目时,没敢直接让它生成main.c——而是先让它帮我重写一个已有的ADC采样校准函数。三分钟,它输出了带注释、符合CMSIS标准、还主动加了溢出保护的版本…

2026/9/16 6:19:26

转录组数据去批次效应:ComBat、ComBat-seq与removeBatchEffect实战指南

拿到转录组数据,我第一步永远是先看PCA图。这个习惯帮我避免过很多次“跑完差异分析却根本解释不了结果”的尴尬。不管你是从GEO下载多个数据集合并,还是自己同一批样本分了几次建库测序,批次效应都是绕不开的问题。尤其是整合公共数据做挖掘…

2026/9/16 6:19:26

小米版Codex实战:Codex CLI接入DeepSeek配置与报错排查指南

最近社区里流传一句话:“小米版 Codex,干活有点猛啊。”我第一次看到“小米版 Codex”这个组合时还挺懵的,Codex 不是 OpenAI 的编程智能体工具吗,跟小米有什么关系?翻了一圈留言和配置记录才明白,这是中文…

2026/9/16 6:19:26

Ragflow实战指南:复杂文档RAG的语义解析与生产落地

1. 项目概述:为什么Ragflow在复杂文档RAG实战中不可替代?最近三个月,我连续落地了7个企业级RAG项目,从法律合同审查、医疗文献检索到制造业设备手册问答,几乎每个项目都卡在“文档太杂”这一步——PDF里混着扫描图、Ex…

2026/9/16 6:14:26

YuE模型解析:AR-NAR混合架构实现快准兼得的中文生成

1. 项目概述:从“YuE”到可复现的AR-NAR混合建模实践最近在Hugging Face上刷到一个叫“YuE”的模型,点进去发现它既不是传统自回归(AR)语言模型,也不是纯非自回归(NAR)生成器,而是一…

2026/9/15 4:54:30

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/16 0:04:09

PHP源码部署实战:从环境配置到运行情侣游戏全攻略

简介:这是一套面向情侣互动场景的PHP完整源码,集成情侣飞行棋、真心话大冒险、情趣骰子等玩法,并内置完整分销制度,可自定义多种返佣比例,源码完全开源无加密,支持微信无感自动授权登录与第三方授权&#x…

2026/9/15 14:22:53

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/15 21:31:11

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/15 11:42:23

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码