Service Worker 缓存策略怎么让 React 页面首次加载更快?

UX-朱莉 阅读 108

我在用 Create React App 搭的项目里加了 Service Worker,想优化首屏加载速度。但发现用户第一次访问时还是得等所有 JS 加载完才能看到内容,缓存好像没起作用。我试过在 sw.js 里用 cache-first 策略,但不确定是不是注册时机或缓存逻辑写错了。

这是我在 index.js 里注册 SW 的代码:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js')
      .then(reg => console.log('SW registered:', reg))
      .catch(err => console.log('SW failed:', err));
  });
}

是不是应该在 build 之后生成 precache 列表?或者我的缓存策略根本没覆盖到入口 HTML 文件?

我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
Newb.爱菊
首先你要知道,Service Worker 的缓存策略对于优化首次加载速度确实很重要,但是需要注意的是,Service Worker 需要一定的激活时间,并且首次加载的时候用户浏览器并没有缓存任何资源,所以还是会等待所有的 JS 加载完成。我们可以通过一些调整来优化这个过程。

首先你要确认的是,你是否已经使用了 workbox 来生成 precache 列表。Create React App 默认集成了 workbox,可以很方便地生成你需要的 precache 列表。你可以在 src/index.js 或者 src/service-worker.js 中找到相关的配置。

接下来,我们来看一下你的 sw.js 文件,确保它正确地处理了缓存策略。首先你要确保你的 Service Worker 能够正确地缓存你的 HTML 文件。默认情况下,workbox 会帮你处理静态资源的缓存,但是你可能需要手动添加对 HTML 文件的缓存策略。以下是一个示例:

// sw.js

// 引入 workbox 库
import { CacheFirst, StaleWhileRevalidate } from 'workbox-strategies';
import { registerRoute } from 'workbox-routing';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { ExpirationPlugin } from 'workbox-expiration';
import { precacheAndRoute } from 'workbox-precaching';

// 自动处理 precache 列表中的文件
precacheAndRoute(self.__WB_MANIFEST);

// 对 HTML 文件使用 cache-first 策略
registerRoute(
({ request }) => request.destination === 'document',
new CacheFirst({
cacheName: 'html-cache',
plugins: [
new CacheableResponsePlugin({
statuses: [200],
}),
new ExpirationPlugin({
maxEntries: 1,
maxAgeSeconds: 24 * 60 * 60, // 缓存一天
}),
],
})
);

// 对 CSS 和 JavaScript 文件使用 stale-while-revalidate 策略
registerRoute(
({ request }) => request.destination === 'script' || request.destination === 'style',
new StaleWhileRevalidate({
cacheName: 'static-resources',
plugins: [
new CacheableResponsePlugin({
statuses: [200],
}),
new ExpirationPlugin({
maxEntries: 50,
maxAgeSeconds: 30 * 24 * 60 * 60, // 缓存一个月
}),
],
})
);


这段代码首先引入了一些必要的 workbox 工具,然后通过 precacheAndRoute 自动处理 precache 列表中的文件。接着,我们分别对 HTML 文件和静态资源(CSS 和 JavaScript 文件)设置了不同的缓存策略。对于 HTML 文件,我们使用了 CacheFirst 策略,这样可以确保即使服务器返回了新的 HTML 文件,我们也先从缓存中读取,从而加快首次加载速度。对于静态资源,我们使用了 StaleWhileRevalidate 策略,这样可以在返回缓存的同时异步更新缓存,保证资源的最新性。

最后,确保你的 index.js 文件中注册 Service Worker 的代码是正确的。你的代码看起来没问题,但为了保险起见,可以稍微简化一下:

// index.js

if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
});
}


这里只是将 sw.js 改为了 service-worker.js,如果你的文件名不同,请相应修改。确保你的 Service Worker 文件路径正确无误。

希望这些调整能帮助你优化 React 页面的首次加载速度。如果还有其他问题,尽管问我,有时候可能需要更多的调试信息来定位问题。
点赞
2026-03-23 01:03