Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] 更细粒度的 splitChunks 策略 #858

Open
fengzilong opened this issue Oct 18, 2021 · 0 comments
Open

[RFC] 更细粒度的 splitChunks 策略 #858

fengzilong opened this issue Oct 18, 2021 · 0 comments

Comments

@fengzilong
Copy link
Contributor

fengzilong commented Oct 18, 2021

rax-app 目前的 splitChunks 策略比较粗暴,node_modules 中被引用 2 次及以上的依赖都会打到 vendor.js 中

场景举例

场景一

假如一个工程有一些功能页面(比如登录/商品详情/个人中心...)和很多活动会场页面

会场页面引用了一堆的 node_modules 依赖,被打到 vendor.js 中后,会导致以下问题

  1. 功能页面 不得不加载 vendor.js (大部分依赖没有使用到),对性能有较大影响
  2. vendor.js 比较容易变动,无法充分利用 http 缓存

场景二

假如有两个 npm 包:
包 A 体积 160kB
包 B 体积 2kB

他们被打到了一个 chunk 中,在 B (2kB)发生变化时,会导致用户需要重新下载 162kB,对缓存有很大影响

优化方案

next.js 之前的方案是通过计算 依赖使用率,比如被 50% 以上的页面依赖时,才会打到 vendor.js 中,但是这种方式仍然不是最佳的方案,仍然会有上面的问题

后面 next.js 换了一种更好的 splitChunks 策略(和 chrome 团队一起合作,通过实验室数据和真实用户数据证明该策略确实有效),该策略可以减少原本的 vendor 体积,提升页面性能,同时可以进行更高效的 http 缓存

该方案后面也被 gatsby 采用

vercel/next.js#7696
gatsbyjs/gatsby#22253

方案详述

chunks 描述及拆分原因如下:

  • framework
    描述:指定的框架 npm 包,比如 rax/driver-universal/...
    拆分原因:一般情况下这部分包不会升级,可以跨构建生成一致的 hash,可以跨多次构建在浏览器端命中缓存
  • common
    描述:每个页面 entrypoint 都引用的 npm 包(或者依据使用率拆分,80% 的页面都引用即可拆分)
    拆分原因:用户访问不同页面时,这部分公用的 npm 包,不需要重新下载,比如访问完 A 页面,再访问 B 页面,公共的依赖直接走缓存
  • shared
    描述:被引用两次及以上的 npm 包
    拆分原因:拆出去可以减少主 chunk 的体积,同时提高缓存复用,是对 common 的一个补充(可选)
  • lib-[name]
    描述:体积大于 160kB 的 npm 包,单独拆出自己的一个 chunk
    拆分原因:如果体积大于 160kB 的 npm 包被放入其他 chunk,如果这个 chunk 内其他较小的 npm 包改动,会导致整个 chunk 发生变化,需要重新下载,成本较大
  • page
    描述:默认 chunk,页面本身的代码

该方案在移动端可以稍作调整,减少拆分的 chunks 数

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant