HOW - prefetch 二级页面实践

文章目录

  • [方法一:使用 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 /> },
];

你可以在 IndexPageuseEffect 中触发 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> 标签

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>
  );
}

注意,如果二级页面特别多,比如十几个甚至几十个,一次性全部预加载反而会拖慢首页加载。

推荐策略:

  1. 对访问概率高的页面在首页预加载(比如「关于我」)。
  2. 对不常访问的页面延迟到用户第一次 hover / focus 时再预加载。
ts 复制代码
<a
  href="/about"
  onMouseEnter={() => import("./About")}
>
  About
</a>

这样用户第一次将鼠标移到链接上时,就已经预取完成,点击时是"秒开"。

最推荐的实践组合是:

  1. 在首页 useEffect 中预加载 1~3 个高频页面。
  2. 对其余页面用 hover 延迟预加载。
  3. 保持首页首屏加载轻量。
相关推荐
hh随便起个名1 小时前
力扣二叉树的三种遍历
javascript·数据结构·算法·leetcode
我是小路路呀2 小时前
element级联选择器:已选中一个二级节点,随后又点击了一个一级节点(仅浏览,未确认选择),此时下拉框失去焦点并关闭
javascript·vue.js·elementui
程序员爱钓鱼2 小时前
Node.js 编程实战:文件读写操作
前端·后端·node.js
PineappleCoder2 小时前
工程化必备!SVG 雪碧图的最佳实践:ID 引用 + 缓存友好,无需手动算坐标
前端·性能优化
JIngJaneIL2 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
敲敲了个代码2 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web
澄江静如练_3 小时前
列表渲染(v-for)
前端·javascript·vue.js
JustHappy3 小时前
「chrome extensions🛠️」我写了一个超级简单的浏览器插件Vue开发模板
前端·javascript·github
Loo国昌3 小时前
Vue 3 前端工程化:架构、核心原理与生产实践
前端·vue.js·架构