Umi 如何生成 preload_helper.js?从构建期生成到运行时验证的完整指南
【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi
用 Umi 写页面时,切换路由常常要干等对应的 JS 分块下载完。Umi 的构建产物里有个 preload_helper.js,它提前告诉浏览器当前路由要用哪些资源,让下载先跑起来。下面结合源码讲清楚:什么条件才会生成它、里面写了什么、怎么在自己的项目里验证。
preload_helper.js 在什么情况下生成
这个文件并非所有项目都会产出。Umi 的 routePreloadOnLoad 功能源码中有一个自检逻辑,四个条件同时满足才会启用:
- package.json 里有
name字段(运行时要用它做资源标识前缀) - 使用默认构建器,没有开启
vite模式 - 是单页应用,不是
mpa多页模式 - 路由加载方式是 ESM,即
routeLoader.moduleType为'esm'
不符合时最典型的情况如下:
| 场景 | 结果 |
|---|---|
未设置vite或mpa之外的条件均满足 | 正常生成 |
package.json 缺少name | 不生成 |
开启了vite模式 | 不生成 |
routeLoader.moduleType设为'cjs' | 不生成 |
路由与资源的映射表是如何算出来的
满足条件后,构建在onBuildComplete钩子里走三步,把"路由 → 资源"的映射定下来:
- 读取构建统计信息,跳过入口分块,只保留各分块里的
.js和.css文件; - 顺着每个分块的来源记录,找出由路由入口
route.tsx引出的模块,反查回页面源码路径,得到"哪些分块文件属于哪个路由文件"; - 遍历路由表,每条路由再向上累加父级路由(如 layout)的资源,最终收敛成"路由路径 → 资源列表"。
落盘的数据被压缩成四个字段:
{ p: 'my-app', // 包名 b: 'webpack', // 构建器类型 f: [['p__home.js', 3]],// [分块文件名, 分块 ID] r: { '/home': [0] } // 路由路径 -> f 的下标列表 }其中r里的路由不是按配置顺序写的,而是参照 react-router 的评分规则排序:静态段落分值高于:id动态段,动态段又高于*通配段。运行时按这个顺序找,常见静态路由能优先命中。
加载之后这个文件做了什么
构建时 Umi 通过addHTMLHeadScripts在 HTML 头部引用该脚本。页面加载后,脚本只做三件事:
- 取当前
location.pathname,剥掉base前缀得到真实路由路径;不匹配 base 时直接跳过; - 先精确匹配静态路由,未命中再按动态路由规则逐一尝试(
:id转成[^/]+,*转成.+); - 命中后为 js 插入
<script src ... async>,为 css 插入<link rel="preload" as="style">,并在标签上挂data-webpack:包名:分块ID形式的属性,方便运行时识别归属。
生产构建会用 terser 压缩这段脚本;开启hash配置后,文件名还会带 8 位哈希后缀,便于长缓存失效。可读版的运行逻辑见 preloadRouteFilesScp.ts,它和模板 preloadRouteFilesScp.js 是同一份逻辑的两种形态。
如何在自己项目里验证生效
实操看三处:
- 构建产物:
umi build后确认dist/preload_helper.js是否存在(开 hash 时带后缀); - 浏览器查看源码:进入任一页面,
<head>里应多出对应路由的<script>与<link>标签; - 配置侧:真正控制它的是
routeLoader.moduleType:
// config/config.ts export default { routeLoader: { // 默认即 'esm';改成 'cjs' 会停止生成该文件 moduleType: 'esm', }, };多数项目默认就是'esm',无需额外配置。注意别和routePrefetch混淆:那个配置项负责"按用户意图预取",默认关闭,是另一套机制。两项的详细类型可查 routeLoader 官方配置说明。
需要留意的边界情况
- 重定向路由不参与映射,源码直接跳过,空路由不会带来多余预取;
wrappers通过嵌套路由实现,包装路由与业务路由共享同一absPath,Umi 会取资源列表更长的一份,包装层资源不会丢;- Mako 会把极小的异步分块并进入口分块,此时该路由没有独立文件可预取,属于正常现象;
- 运行时只处理 js 和 css,其他资源类型不介入。
收尾建议
- 开
hash部署后,核对 HTML 中的脚本引用与 dist 实际文件名一致,避免自定义部署脚本漏拷这个文件导致 404; - 发现某页资源没被预取,先按"如何验证"一节确认文件已生成,再排查该路由是否为重定向、或分块被并进了入口;
- 不要手工拼预加载逻辑,用浏览器 Network 面板实测首屏资源发起时间,再决定是否需要调整
base与publicPath适配部署路径。
【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考