HOW - prefetch 二级页面实践
文章目录
- 方法一:使用 import()
- 方法二:使用 link rel="prefetch" 或 link rel="preload"
- 方法三:借助 Vite 插件自动预取
- 小结
- 批量预加载
在 Vite + React 项目中,如果你希望在访问首页(index
页面)时提前预加载(prefetch)二级页面的资源,从而在用户点击进入时加快加载速度,有几种常见、有效的方式。
方法一:使用 import()
如果你的二级页面是通过 动态 import(代码分割) 实现的(这是 Vite 推荐的懒加载方式),那么你可以手动对它的资源进行预取(prefetch)。
比如你的路由是这样定义的
// router.tsx
import { lazy } from "react";const IndexPage = lazy(() => import("./pages/Index"));
const AboutPage = lazy(() => import("./pages/About")); // 二级页面export const routes = [{ path: "/", element: <IndexPage /> },{ path: "/about", element: <AboutPage /> },
];
你可以在 IndexPage
的 useEffect
中触发 import()
,这样浏览器就会预加载资源(但不会执行)
// pages/Index.tsx
import { useEffect } from "react";export default function Index() {useEffect(() => {// 预取 About 页面的资源import("./About");}, []);return (<div><h1>首页</h1><a href="/about">去 About</a></div>);
}
这里 ./About
并不是指构建后的实际路径,而是与Index同一层级下的About.tsx
。Vite 在打包时会自动把这个 import("./About")
替换成对 about-yyyy.js
的懒加载请求。你不需要知道它的真实文件名。
优点:
- 简单好用,不需要额外依赖。
- Vite 在 build 后会自动生成 chunk,对应资源会被预取。
- 实际浏览器加载时,用户点击
/about
基本是即时打开。
注意:
- 这种方式属于「预加载模块」,不是真正意义的浏览器
rel="prefetch"
标签。 - 适合用在用户很大概率会访问的二级页面上。
方法二:使用 link rel=“prefetch” 或 link rel=“preload”
如果你希望更明确地让浏览器在空闲时预取资源,可以在首页渲染时插入一个 <link>
标签
import { useEffect } from "react";export default function Index() {useEffect(() => {const link = document.createElement("link");link.rel = "prefetch";link.href = "/assets/AboutPage.xxx.js"; // 构建后的 chunk 路径document.head.appendChild(link);}, []);return <h1>首页</h1>;
}
这种方式比较麻烦的是:
- 你要知道
About
页面的构建产物路径(可以通过 manifest.json 或动态 import 的返回值获取)。 - 更适合对静态资源(图片、视频、大文件)做预加载。
方法三:借助 Vite 插件自动预取
还有一种自动化的方式是使用社区插件,例如 👉
vite-plugin-pwa
(适合离线场景)
vite-plugin-prefetch
(更灵活的 prefetch)
在 vite.config.ts
中配置:
import prefetch from "vite-plugin-prefetch";export default {plugins: [prefetch({rel: "prefetch",include: ["about"], // 你想要预取的 chunk 名称}),],
};
优点:
- 自动插入
<link rel="prefetch">
。 - 不需要在组件中写逻辑。
小结
方式 | 特点 | 适合场景 |
---|---|---|
import() 预加载 | 简单、推荐 | 二级页面懒加载 |
<link rel="prefetch"> | 控制更细,但需路径 | 预取静态资源 |
React Router 预加载 | 更规范 | 使用 react-router v6+ |
Vite 插件自动化 | 零侵入 | 大型项目,多个页面 |
批量预加载
如果你有多个页面,也可以并行预加载:
useEffect(() => {Promise.all([import("./About"),import("./Contact"),import("./Help"),]);
}, []);
当然也可以封装一个工具函数:
// utils/prefetchRoutes.ts
export async function prefetchRoutes(paths: string[]) {const prefetchMap: Record<string, () => Promise<any>> = {"/about": () => import("../pages/About"),"/contact": () => import("../pages/Contact"),"/help": () => import("../pages/Help"),};await Promise.all(paths.map((path) => prefetchMap[path]?.()));
}// Index.tsx
import { useEffect } from "react";
import { prefetchRoutes } from "../utils/prefetchRoutes";export default function Index() {useEffect(() => {prefetchRoutes(["/about", "/contact", "/help"]);}, []);return (<div><h1>首页</h1><a href="/about">About</a><a href="/contact">Contact</a><a href="/help">Help</a></div>);
}
注意,如果二级页面特别多,比如十几个甚至几十个,一次性全部预加载反而会拖慢首页加载。
推荐策略:
- 对访问概率高的页面在首页预加载(比如「关于我」)。
- 对不常访问的页面延迟到用户第一次 hover / focus 时再预加载。
<ahref="/about"onMouseEnter={() => import("./About")}
>About
</a>
这样用户第一次将鼠标移到链接上时,就已经预取完成,点击时是“秒开”。
最推荐的实践组合是:
- 在首页 useEffect 中预加载 1~3 个高频页面。
- 对其余页面用 hover 延迟预加载。
- 保持首页首屏加载轻量。