文章目录
- [方法一:使用 import()](#方法一:使用 import())
- [方法二:使用 link rel="prefetch" 或 link rel="preload"](#方法二:使用 link rel="prefetch" 或 link rel="preload")
- [方法三:借助 Vite 插件自动预取](#方法三:借助 Vite 插件自动预取)
- 小结
- 批量预加载
在 Vite + React 项目中,如果你希望在访问首页(index
页面)时提前预加载(prefetch)二级页面的资源,从而在用户点击进入时加快加载速度,有几种常见、有效的方式。
方法一:使用 import()
如果你的二级页面是通过 动态 import(代码分割) 实现的(这是 Vite 推荐的懒加载方式),那么你可以手动对它的资源进行预取(prefetch)。
比如你的路由是这样定义的
ts
// 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()
,这样浏览器就会预加载资源(但不会执行)
ts
// 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>
标签
ts
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
中配置:
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 插件自动化 | 零侵入 | 大型项目,多个页面 |
批量预加载
如果你有多个页面,也可以并行预加载:
ts
useEffect(() => {
Promise.all([
import("./About"),
import("./Contact"),
import("./Help"),
]);
}, []);
当然也可以封装一个工具函数:
ts
// 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 时再预加载。
ts
<a
href="/about"
onMouseEnter={() => import("./About")}
>
About
</a>
这样用户第一次将鼠标移到链接上时,就已经预取完成,点击时是"秒开"。
最推荐的实践组合是:
- 在首页 useEffect 中预加载 1~3 个高频页面。
- 对其余页面用 hover 延迟预加载。
- 保持首页首屏加载轻量。