Partial Bundling
Partial Bundling
是 Farm 用于打包模块的策略,与其他 bundler的做法类似,但 Farm 的 Partial Bundling
的目标不同。
与其他 bundler 不同,Farm 不会尝试将所有内容打包在一起,然后使用splitChunks
等优化将它们分开,相反,Farm 会将项目直接打包到多个输出文件中。 例如,如果启动一个 html 页面需要数百个模块,Farm 将尝试直接将它们打包到 20-30 个输出文件中。 Farm 将这种行为称为Partial Bundling
。
Farm Partial Bundling 的目标是:
- 减少请求数量和请求层次:使数百或数千个模块请求减少到20-30个请求,并避免由于依赖层次而逐个加载模块,这将使资源加载更快。
- 提高缓存命中率:当模块更改时,确保只有少数输出文件受到影响,以便更多缓存可以用于在线项目。
对于传统的 bundler,我们可能很难配置复杂的splitChunks
或manualChunks
来实现上述目标,但在 Farm 中,通过Partial Bundling
原生支持它。
请参阅 RFC-003 局部打包 以获取更多技术细节。
设计动机
现在 Web 构建工具中处理模块的方法主要有两种:打包或使用原生 ESM。 但它们都有缺点:
- 对于打包,bundler 的目标是将所有内容打包在一起,然后将它们拆分出来进行优化,但拆分通常很难配置,并且很难手动平衡资源加载性能和缓存命中率。
- 对于原生esm,每个模块都可以单独编译、缓存,但是当有数百个模块请求时,加载性能受到严重影响。
所以我一直在想,如果有一种策略可以避免这两个极端——也许我们可以进行局部打包? 我们可以直接将项目自动打包到几个有限的、大小平衡的资源中。 我将这种想法命名为 Module Merging
- 在打包和不打包之间找到平衡,仅打包一些相关模块以提高加载性能而不损失缓存粒度。
后来我将
Module Merging
改名为Partial Bundling
,因为我认为Partial Bundling
可以更准确地表达我的想法。
Partial Bundling 规则
在本节中,我们将通过示例介绍
Partial Bundling
使用的基本规则。
首先我们研究一个基本的 React 项目示例。 对于像下面这样的基本 react 项目,我们在入口脚本中导入 react 和 react-dom:
import React from 'react';
import { createRoot } from 'react-dom/client';
import './index.scss';
const container = document.querySelector('#root');
const root = createRoot(container);
root.render(
<>
<div>Index page</div>
</>
);
打包结果将如下所示:
./dist/
├── index_9c07.49b83356.js # 包含react-dom
├── index_a35f.0ac21082.js # 包含./index.tsx
├── index_b7e0.7ab9ca2d.js # 包含react及其依赖项
├── index_ce26.7f833381.css # 包含./index.scss
└── index.html # 包含./index.html