505 - 《前端,本应更快》

发布于 2024年12月29日

上个月末在内网写的一篇长文,脱敏后贴下到这里,方便我在后面的文章里 ref 。

1、现状。

之前偶尔翻到「内部蚂蚁体验」的网站,体验并不好。超长的 loading 时间,很明显的加载瀑布流。如果打开控制台,会发现他需要加载 90 多个 js 资源,光 react-dom.production.min.js 就被加载了 6 份,就这居然还没有冲突。

图:蚂蚁体验的加载效果图。(脱敏后删除)

加载瀑布流这个问题应该是随着组件化而来的,就算制作精良的雨燕也不能幸免。只要你用 useEffect 加载数据,就会有;就算不用,也可能有,比如下层组件依赖上层组件的数据。

图:雨燕的加载效果图。(脱敏后删除)

同时,我们上的一些技术方案也多多少少加剧了这类性能问题,都是权衡。比如一些庞大的三方库、全站微前端、auto externals、esbuild as minifier、mako 等等,方案肯定都是为解问题而生,但他们也多少以牺牲部分 UX 为代价。

此外,我们在请求缓存、stale-while-revalidate、基于路由的 load 和 preload 策略上都实践甚少。而这些是提升页面 load 之后的请求交互和路由切换速度感体验的关键。一些标杆产品比如雨燕和语雀,其首页模块都实现了 stale-while-revalidate(或者只是缓存),见下图,但如果加上 preload,会让首次切换也有秒开的体验,UX 会更好。

图:两张内部网站的交互图(脱敏后删除)

Ant Design Pro 默认的脚手架和我们通过工具产出的页面和组件也无这些方案。

2、基于路由的 load、preload、缓存 和 stale-while-revalidate。

每个方案都有接入成本,这也是为啥虽然这些方案体验好,但覆盖率都挺低,比如语雀大部分的切换都是无缓存刷新的。而覆盖率就决定了整体的 UX 体验。之前也写过《最佳实践 2022-8:请求方案最佳实践》《Bigfish 4 特性 03:默认最快的请求》,但出于推广、研发习惯、接入和培训成本等因素,这些方案目前都比较少人使用。

从接入成本来看,缓存和 stale-while-revalidate 其实还好,只要借助 swr@tanstack/query 库就可以。但 (pre)load 就要复杂一些,得借助编译时,通常需要框架配合。同时 (pre)load 需要 load 的除了 loader 方法(请求),还有 js、css、assets 等,这就需要借助构建工具和框架,让 url、请求和静态资源文件之间有个映射关系。

所以,如果这些方案我们全都要,同时还想要较少的接入成本,只用 swc 或 @tanstack/query 是不够的。需要基于路由定义 loader 方法,然后让框架内置 mini 版的 swr 或 @tanstack/query,处理请求的缓存和 stale-while-revalidate,以及对路由对应的 component 所需的 js 和 css 做代码拆分和按需加载。同时,这一切都要保证最大可能并发。

然后用户只需要这么定义 loader。当然,实际情况还会更复杂一些,比如,1)如何拆分 loader 和 component,loader 应该随主包,因为比较小而且需要尽早发起以避免请求瀑布流,2)子路由依赖父路由的数据怎么办?方法比较多,通过 context 或者显式依赖另一个路由的数据等。

// src/pages/users.tsx
export async function load

内容预览已结束

此内容需要会员权限。请先登录以查看完整内容。