没网的时候也能看:给前端页面加一层 Service Worker 做成 PWA

举报
海是岛思念的泪 发表于 2026/09/10 11:13:17 2026/09/10
【摘要】 弱网或断网时普通网页直接白屏。这篇用 Service Worker 给前端加一层离线缓存:拦截请求、优先返回缓存的 app shell,配合 manifest.json 还能被加到桌面全屏打开。重点讲注册、缓存策略、更新机制和几个容易忽略的注意点。

地铁里打开网页白屏、飞机上想看个帮助页看不了——这些糟心事的源头是:普通网页一旦断网,浏览器找不到资源就直接挂。给站点加一层 Service Worker(SW),让它帮你在后台拦截请求、从缓存里兜底,体验立刻不一样。再配个 manifest,还能被"添加到主屏幕"当半个 App 用。这篇把最小可用做法拆开。

image.png

一、Service Worker 到底是什么

SW 是跑在浏览器背后的一个独立脚本,不绑定某个页面。它能拦截你站点发出的网络请求,于是你可以决定:这个请求是去网络拿,还是直接返回之前缓存的内容。这就是离线的关键——请求根本没真的发出去,SW 在中间就截住了。

二、注册 + 缓存 app shell

主线程里注册 SW(注意 SW 文件必须在站点根目录或对应作用域下):

// main.js
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(() => console.log('SW 已注册'))
}

SW 自身用生命周期钩子工作。install 阶段缓存应用外壳(HTML/CSS/JS 这些骨架):

// sw.js
const CACHE = 'v1'
const SHELL = ['/', '/index.html', '/app.js', '/style.css']

self.addEventListener('install', (e) => {
  e.waitUntil(caches.open(CACHE).then(c => c.addAll(SHELL)))
})

self.addEventListener('fetch', (e) => {
  e.respondWith(
    caches.match(e.request).then(cached => cached || fetch(e.request))
  )
})

fetch 事件里:缓存命中就直接返回(cache-first),没命中才走网络。断网时所有请求都走缓存分支,页面照常开。

三、manifest 让它像个 App

建一个 manifest.json,浏览器才会弹出"添加到主屏幕":

{
  "name": "我的工具",
  "short_name": "工具",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#fff",
  "icons": [{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" }]
}

在 HTML 头里 <link rel="manifest" href="/manifest.json"> 引用即可。用户加到桌面后,打开是全屏、没有浏览器地址栏,观感接近原生 App。

两种缓存策略对比:

策略 行为 适用
cache-first 先查缓存,没有才网络 静态资源、app shell
— network-first 先试网络,失败回缓存 需要较新数据的页面
stale-while-revalidate 立即返缓存,同时后台更新 能容忍短暂陈旧的内容

几个小提醒

  • 作用域限制。SW 文件放 /sw.js 才能管整个站;放 /sub/sw.js 只能管 /sub/ 以下。位置别放错。
  • 更新要主动。你改了 sw.js,旧 SW 还在跑。新版本在 install 后进入 waiting,需要 skipWaiting() 或用户关闭重开才生效。调试时记得在 DevTools 的 Application 面板里手动"Update"或勾"Update on reload"。
  • 必须 HTTPS。SW 只在 https(或 localhost 调试)下生效,http 站点用不了,这是浏览器安全限制。
  • 缓存版本号记得升。上面 CACHE = 'v1',发版改了资源就改个版本号,旧缓存自然失效,避免用户一直看老页面。
  • 别缓存带用户隐私的接口。app shell 缓存没事,但涉及账号的接口走 network-first 甚至不缓存更稳妥。

简单总结一下

PWA 不需要一上来就做得多复杂,先把"SW 缓存 app shell + manifest 可加桌面"这两步做了,离线可用和入口体验就都有了。它不神奇,就是浏览器帮你把"本该去网络拿的东西"提前存了一份。小工具类、文档类、内部系统类站点尤其值得加,用户感知明显。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。