• 隐私政策
  • 联系我们
  • 关于我们
2026 年 7 月 2 日 星期四
聚赢方舟
广告
  • 首页
  • 快讯 7x24
  • 行业新闻
  • 商业动态
  • 股市风云
  • 期货研报
  • 基金财讯
  • 贵金属
No Result
View All Result
  • 首页
  • 快讯 7x24
  • 行业新闻
  • 商业动态
  • 股市风云
  • 期货研报
  • 基金财讯
  • 贵金属
No Result
View All Result
聚赢方舟
No Result
View All Result
Home 基金财讯

用户打开飞行模式都能打开你的网站?Service Worker 做离线缓存,PWA 实战

by 聚赢方舟
2 月 ago
in 基金财讯
Reading Time: 12 mins read
A A
分享至微博分享给朋友


ADVERTISEMENT

你坐飞机,关掉网络,旁边小哥还在刷抖音 (离线缓存好的视频)。你打开自己的网站,白屏,报错。你默默关上手机,心想:「要是我的网站也能离线看就好了。」 今天我们就来给你的网站装上 「离线小精灵」——Service Worker。以后用户没网也能访问,还能把网站装到手机桌面,像原生 App 一样。

前言

PWA(Progressive Web App) 这个概念喊了好几年,但真正用上的网站不多。其实它没那么玄乎,核心就是 Service Worker——一个在浏览器后台独立运行的 JS 线程,能拦截网络请求、缓存资源、推送通知。

加了 Service Worker 的网站,就算用户开飞行模式,只要之前访问过,照样能看到页面 (至少看到缓存过的内容)。而且速度极快,因为资源从本地取,不用等网络。今天我们就从零给一个静态网站加上离线缓存,顺便让它 「可安装」。

一、Service Worker 生命周期:四步走

Service Worker 不是一上来就接管所有请求的,它有严格的生命周期:

  1. 注册:主线程告诉浏览器:「嘿,去下载这个 sw.js 文件。」
  2. 安装:浏览器下载、解析、执行 sw.js 里的 install 事件。通常在这里缓存核心资源。
  3. 激活:旧 Service Worker 被替换,新 SW 接管控制权。可以在 activate 事件里清理旧缓存。
  4. 空闲/运行:之后所有 fetch 请求都会被 SW 拦截。

注意:SW 只在 HTTPS(或 localhost) 下生效,因为可以拦截网络,不安全。

二、最简单的 Service Worker:离线回退页面

我们先写一个极简版 sw.js,让用户离线时看到一个 「你已离线」 的页面。

// sw.js
const CACHE_NAME = 'my-pwa-cache-v1';
const OFFLINE_URL = '/offline.html';

// 安装时缓存离线页面
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => cache.add(OFFLINE_URL))
  );
  // 强制等待中的 SW 立即激活
  self.skipWaiting();
});

// 激活时清理旧缓存
self.addEventListener('activate', (event) => {
  event.waitUntil(
    caches.keys().then((keys) => {
      return Promise.all(
        keys.filter(key => key !== CACHE_NAME).map(key => caches.delete(key))
      );
    })
  );
  self.clients.claim();
});

// 拦截请求,离线时返回缓存
self.addEventListener('fetch', (event) => {
  if (event.request.mode === 'navigate') {
    // 页面导航请求
    event.respondWith(
      fetch(event.request).catch(() => caches.match(OFFLINE_URL))
    );
  } else {
    // 其他资源走缓存优先策略 (稍后优化)
    event.respondWith(
      caches.match(event.request).then((response) => {
        return response || fetch(event.request);
      })
    );
  }
});

然后在 index.html 里注册:

<script>
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
      navigator.serviceWorker.register('/sw.js').then(reg => {
        console.log('SW 注册成功', reg);
      }).catch(err => {
        console.log('SW 注册失败', err);
      });
    });
  }
</script>

现在你打开网站,开飞机模式 (或 DevTools → Network 离线),刷新页面,应该会显示 offline.html。说明 SW 已经拦下了请求。

三、缓存策略:别把所有鸡蛋放一个篮子

上面的代码对所有资源都用了 「缓存优先」——先查 cache,没有才网络。这会导致一个问题:如果某个资源之前缓存过,即使服务器更新了,用户也看不到新版本。所以需要根据资源类型选择策略。

常用策略:

  • Cache First(缓存优先):适合不常变的图片、字体、CSS 库。速度快。
  • Network First(网络优先):适合 API 数据、HTML 页面。先尝试网络,失败再读缓存。
  • Stale-While-Revalidate:先返回缓存 (如果有),同时后台更新缓存。兼顾速度和新鲜度。
  • 仅网络:永远不缓存 (如支付接口)。
  • 仅缓存:永远从缓存取 (如离线页面)。

我们改一下 fetch 事件:

self.addEventListener('fetch', (event) => {
  const url = new URL(event.request.url);
  // 如果是 API 请求,走网络优先
  if (url.pathname.startsWith('/api/')) {
    event.respondWith(
      fetch(event.request).catch(() => caches.match(event.request))
    );
    return;
  }
  // 如果是静态资源 (js、css、图片),走缓存优先
  if (/\.(js|css|png|jpg|webp)$/.test(url.pathname)) {
    event.respondWith(
      caches.match(event.request).then((cached) => cached || fetch(event.request))
    );
    return;
  }
  // 其他 (如 HTML) 走 stale-while-revalidate
  event.respondWith(
    caches.open(CACHE_NAME).then(async (cache) => {
      const cached = await cache.match(event.request);
      const fetchPromise = fetch(event.request).then((response) => {
        cache.put(event.request, response.clone());
        return response;
      }).catch(() => cached);
      return cached || fetchPromise;
    })
  );
});

这样,你的网站既能离线访问,又能及时更新动态内容。

四、用 Workbox 简化代码

手写缓存策略很麻烦,尤其还要处理版本、过期、缓存清理。Google 出品了 Workbox,一套工具库,几行配置搞定复杂策略。

安装 Workbox CLI 或直接在 sw.js 里导入 CDN:

importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.0.0/workbox-sw.js');

const { registerRoute, strategies, cacheableResponse } = workbox;

// 预缓存静态资源 (构建时生成 manifest)
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST || []);

// 图片缓存策略
registerRoute(
  ({ request }) => request.destination === 'image',
  new strategies.CacheFirst({
    cacheName: 'images',
    plugins: [
      new cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
      new workbox.expiration.ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 30 * 24 * 60 * 60 })
    ]
  })
);

// API 网络优先
registerRoute(
  ({ url }) => url.pathname.startsWith('/api/'),
  new strategies.NetworkFirst()
);

配合 webpack/vite 插件,可以自动生成预缓存清单,连 install 里的 cache.add 都不用手动写。

五、让网站可安装 (添加到主屏幕)

PWA 另一大特性:用户可以像装 App 一样把网站装到手机桌面。需要满足三个条件:

  1. HTTPS(或 localhost)
  2. 注册了 Service Worker
  3. 有一个 manifest.json 文件,放在根目录

示例 manifest.json:

{
  "name": "我的离线网站",
  "short_name": "离线站",
  "start_url": "/",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "icons": [
    {
      "src": "/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

在 index.html 里引用:

<link rel="manifest" href="/manifest.json">

之后用户访问网站,浏览器会在地址栏右侧弹出 「安装 App」 的提示。点一下,桌面就多了一个图标,打开后没有浏览器地址栏,像原生 App。

六、推送通知 (可选彩蛋)

Service Worker 还能接收服务器推送的消息,即使网站没打开也能弹出通知。这需要用户授权和后台推送服务 (比如 Firebase Cloud Messaging)。代码稍复杂,但可以实现 「用户关掉浏览器,你也能给他发优惠券提醒」 的效果。

七、实测数据:加了 SW 之后

我用一个 React 静态网站测试:

  • 未缓存:首次加载 1.8s,二次无网白屏。
  • 加了 Workbox 预缓存:首次 2.0s(多下载了 SW 和 manifest),二次无网打开 0.3s(完全离线)。
  • 页面切换速度提升明显,因为路由对应的 JS 也被缓存。

用户从 「等待加载」 变成 「秒开」,体验提升 5 倍以上。

八、坑点与避坑

  • 更新缓存:修改文件后,用户可能还是旧版本。需要更新 CACHE_NAME 版本号,或者在预缓存时用 rev(文件 hash) 解决。Workbox 会自动处理。
  • localhost 测试:记得勾选 DevTools → Application → Service Workers → Update on reload,否则 SW 缓存会干扰。
  • 作用域:SW 默认作用域是 sw.js 所在目录,如果放在根目录,可以控制全站。放在 js/ 下就只能控制 js/ 路径。
  • 调试:Chrome DevTools 的 Application 面板可以看到所有缓存、SW 状态、推送通知。

九、总结:PWA 是前端的 「离线外挂」

  • Service Worker 是浏览器后台独立线程,能拦截请求、缓存资源、推送通知。
  • 生命周期:注册 → 安装 → 激活 → fetch。
  • 缓存策略根据资源类型选择:Cache First、Network First、Stale-While-Revalidate。
  • 搭配 Workbox 可省去手写复杂缓存逻辑。
  • 加上 manifest.json 就能让网站 「安装到桌面」。

下次你坐飞机,打开自己的 PWA 网站,不用网络也能刷内容。同事看了问:「你怎么做到的?」 你就可以把本文甩给他。


评论区聊聊:你的网站支持离线访问吗?遇到过哪些缓存更新问题?

聚赢方舟

专业财经网站

聚赢方舟 (arkxx.com) 网站是长沙聚赢方舟文化传媒有限公司旗下运营的财经资讯门户网站。聚赢方舟致力于为用户提供全面而深入的财经资讯与金融数据分析。网站汇集了最新的市场行情、股票动态、投资策略以及经济趋势,为投资者和财经行业人士提供及时的新闻参考。网站通过高效的数据处理与分析工具,聚赢方舟帮助用户把握市场机会,优化投资决策。

此外,网站还定期发布专业的市场评估报告和财经评论,确保用户能够获得最准确的市场洞察。

方舟日历

2026 年 7 月
一 二 三 四 五 六 日
 12345
6789101112
13141516171819
20212223242526
2728293031  
« 6 月    

标签

中国 中国企业 也不 买了 互联网 假日 养老金 北大 千元 印度 反超 奶茶 家族 工龄 怎么回事 或将 房价 房贷 新能源 新闻 日本 更大 有什么 村官 来了 楼市 江苏 沙特 浙江 特斯拉 电动车 石油 美元 美国 美籍 节日 芯片 让人 越南 长假 防晒 阿里 阿里巴巴 院士 首富

© 2025 长沙聚赢方舟文化传媒有限公司 by 聚赢方舟 - 湘 ICP 备 2025135270 号-1

No Result
View All Result
  • Home

© 2025 长沙聚赢方舟文化传媒有限公司 by 聚赢方舟 - 湘 ICP 备 2025135270 号-1

此网站使用 cookie。继续使用本网站即表示您同意使用 cookie。访问隐私和 cookie 策略.。