HTTP 协议详解
HTTP(Hyper Text Transfer Protocol,超文本传输协议)是 Web 开发中最重要的协议之一。本文将从基础到进阶,全面讲解 HTTP 协议的核心知识点。
HTTP(Hyper Text Transfer Protocol,超文本传输协议)是 Web 开发中最重要的协议之一。本文将从基础到进阶,全面讲解 HTTP 协议的核心知识点。
垃圾回收机制是由引擎来负责的。JS 引擎有很多种(各个浏览器都不同),其垃圾回收机制在一些细节及优化上也略有不同。本文以一些通用的回收算法作为切入,再由市场占有率大的 V8 引擎发展至今对该机制的优化为例。JavaScript 是门魅力无限的语言,关于它的 GC(垃圾回收)方面,你了解多少呢?想来大部分人是因为面试才去看一些面试题从而了解的垃圾回收,那在正式开始之前,给大家列几个小问题,大家可以先想一下答案,带着问题及答案再去看文章。
想象你去一家公司拜访朋友:
对应到计算机世界:
| 现实世界 | 计算机世界 |
|---|---|
| 出示身份证 | 输入用户名密码 |
| 前台核实 | Authentication(认证) |
| 临时工牌 | Token / Session ID |
| 不同门禁权限 | Authorization(授权) |
| 集团工牌通用 | SSO(单点登录) |
| 你把工牌借给朋友 | 会话劫持 / Token 泄露 |
❗ 面试常问:认证(Authentication)和授权(Authorization)的区别?
认证是”你是谁”,授权是”你能做什么”。认证在前,授权在后。很多系统只需要认证(如公开 API 的限流),但授权一定依赖认证。
HTTP 是无状态协议——每次请求都是独立的,服务器记不住”上次和你聊过”。要让前后端互信,必须主动维护一个状态。前端常见的鉴权方式有四种:
| 方式 | 状态存放 | 是否跨域 | CSRF 防护 | 服务端开销 | 典型场景 |
|---|---|---|---|---|---|
| Cookie + Session | 服务端(Session 内存/Redis) | 否 | ❌ 需额外防护 | 高 | 传统 MPA(多页应用) |
| Token(含 JWT) | 客户端(localStorage/内存) | ✅ 是 | ✅ 天然防御 | 低(无状态) | SPA、移动端 API |
| OAuth 2.0 | 第三方认证服务器 | ✅ 是 | ✅ | 中等 | 第三方登录(Google、微信) |
| SSO | 统一认证中心 | 跨站点 | ✅ | 中等 | 公司内部多系统打通 |
这四种方式并非互斥,实际项目中常常组合使用:
Cookie 是服务端塞给浏览器的一小块数据,浏览器会把它存起来,下次请求同一域名时自动带上。
1 | sequenceDiagram |
| 属性 | 说明 | 面试频率 |
|---|---|---|
Expires / Max-Age | 过期时间。不设置则为会话 Cookie(关闭浏览器即失效) | ⭐⭐ |
Domain | 指定哪些域名可以访问。如 .example.com 则子域名都可用 | ⭐⭐ |
Path | 指定路径生效范围,默认 / | ⭐ |
Secure | 仅在 HTTPS 下传输 | ⭐⭐⭐ |
HttpOnly | JS 无法读取(document.cookie 拿不到),防 XSS | ⭐⭐⭐⭐ |
SameSite | 现代 CSRF 防护核心,见下方详解 | ⭐⭐⭐⭐⭐ |
Cookie 由服务端通过 HTTP 响应头 Set-Cookie 设置:
1 | Set-Cookie: sessionId=abc123; Expires=Wed, 21 Oct 2026 07:28:00 GMT; Path=/; Domain=.example.com; Secure; HttpOnly; SameSite=Lax |
配置说明:
Set-Cookie 中指定属性,多个属性用 ; 分隔document.cookie,且无法添加 HttpOnly 等安全属性JS 操作 Cookie
1 | // 设置(只能设置 name=value、Domain、Path、Expires,无法设置 HttpOnly / Secure / SameSite) |
SameSite 是 Chrome 51+ 引入的 Cookie 安全属性,用于限制第三方请求是否携带 Cookie,是目前最有效的 CSRF 防御手段之一。
| 值 | 行为 | 使用场景 |
|---|---|---|
Strict | 完全禁止第三方请求携带,即使是点击链接跳转也不带 | 银行转账等极高安全场景 |
Lax(默认) | 允许 GET 方式的顶级导航携带(点击链接、GET 表单),POST 等方式不携带 | 大多数网站推荐 |
None | 不限制,但必须配合 Secure(仅 HTTPS) | 跨域请求需要携带 Cookie 时 |
CSRF 的攻击原理是:攻击者在自己的页面构造请求,让浏览器带着你的 Cookie 向目标网站发起请求(比如转账)。因为 Cookie 自动携带,服务端无法区分这个请求是用户主动发起的还是被诱骗发起的。
防御手段(从推荐到兜底):
SameSite Cookie(首选):设置 SameSite=Lax。现代浏览器默认行为,阻止 POST 等危险请求跨站携带 Cookie。配置简单、覆盖面广,后端加一行响应头即可——这是当前最推荐的防御方案。
校验 Referer / Origin 头:服务端检查请求来源是否为合法域名。缺点:某些场景(如 HTTPS→HTTP 跳转)浏览器可能不发送 Referer 头。
CSRF Token:服务端在页面中嵌入一个随机 token,提交请求时携带。攻击者无法获取这个 token,因此请求被拒绝。缺点:SPA 需要额外的后端配合。
关键操作加验证码:转账、改密等操作强制用户输入验证码,从根本上阻止 CSRF。
XSS(跨站脚本攻击)是指攻击者在页面中注入恶意脚本,从而读取页面中的一切数据,包括 localStorage。
防御手段:
永远不要在 localStorage 中存敏感信息(如身份证号、银行卡号)。如果必须存 token,要接受 XSS 会导致 token 泄露的风险。
严格防范 XSS(这是根本):
<script> 标签被直接渲染)Content-Security-Policy(CSP)头限制脚本来源v-html / dangerouslySetInnerHTML 仍存在风险使用 HttpOnly Cookie 替代 localStorage 存 token(但如果你的 SPA 需要跨域 API,这条路走不通)
最佳实践:Access Token 放内存,Refresh Token 放 HttpOnly Cookie——XSS 能读到内存中的 Access Token,但有效期短(15 分钟);拿不到 Refresh Token 就无法续期,损失可控。
Domain 可共享现代浏览器默认开启 Cookie,禁用的情况极少。如果真禁用了,使用 URL 参数传递 Session ID 是最常见的替代方案。但要注意:URL 传递 Session ID 容易被截取或泄露(通过 Referer 头),所以主流做法是要求浏览器开启 Cookie,否则提示用户。
✅ 过时内容清理:Flash 沙箱、IE6 时代的 Cookie 问题已全部删除。
⚠️ 重要区分:Session(服务端会话) 和 sessionStorage(浏览器存储) 除了名字相似,没有任何关系!Session 存在服务器内存/Redis 中,sessionStorage 存在浏览器磁盘中。Session 的过期由服务端控制,sessionStorage 关闭即清理。
| 特性 | Cookie | localStorage | sessionStorage |
|---|---|---|---|
| 容量 | ~4KB | ~5MB+ | ~5MB+ |
| 生命周期 | 可设置,默认关闭浏览器即失效 | 永久保存(除非手动清除) | 当前标签页会话,关闭即清除 |
| HTTP 携带 | ✅ 每次请求自动带上 | ❌ 不参与通信 | ❌ 不参与通信 |
| 跨域 | ❌ 绑定域名 | ❌ 同源策略 | ❌ 同源策略 |
| 可访问性 | 同域名所有标签页 | 同源所有标签页 | 仅当前标签页 |
| XSS 风险 | HttpOnly 可防御 | ⚠️ JS 直接读取,风险高 | ⚠️ JS 直接读取,风险高 |
| API 易用性 | 需要自行封装 | 原生接口友好 | 原生接口友好 |
1 | // 存 |
❗ 面试题:localStorage 如何跨标签页通信?
通过storage事件。当同一源下的某个页面修改 localStorage 时,其他页面会触发该事件。
| 存储位置 | XSS 防护 | CSRF 防护 | 跨域 | 场景 |
|---|---|---|---|---|
localStorage | ❌ 直接暴露 | ✅ | ✅ | SPA 常用,需做好 XSS 防护 |
sessionStorage | ❌ 直接暴露 | ✅ | ✅ | 标签页隔离需求 |
| Cookie(HttpOnly + SameSite) | ✅ | ✅(SameSite=Lax) | ❌ | 最安全但限制跨域 |
| 内存变量 | ✅ | ✅ | ✅ | 刷新即丢失 |
最佳实践:将 Access Token 放在内存中,Refresh Token 放在 HttpOnly Cookie 中。这样即使 XSS 也只能拿到短期有效的 Access Token,拿不到可刷新的 Refresh Token。
⚠️ 名称澄清:此处的 Session(会话) 是服务端概念,和浏览器的
sessionStorage没有任何关系。Session 存在服务器内存/Redis 中,由服务端管理其生命周期。
1 | sequenceDiagram |
ConcurrentHashMap / Redis)Session 存在于服务端,它的有效期由服务端配置决定,与”浏览器是否关闭”没有直接关系:
Node.js (express-session) 默认也是 10 分钟无操作即过期。举例:你用手机浏览器登录了知乎,Session 数据存在知乎服务器。你关掉浏览器,知乎服务端的 Session 并不会立即消失——它还会保留十几分钟到半小时,等超时后再被清理。这就是为什么”关浏览器”不等于”退出登录”。
当服务扩展到多台服务器时,Session 存在不同机器上怎么办?
| 方案 | 说明 | 优缺点 |
|---|---|---|
| 粘性会话(Sticky Session) | 负载均衡将同一用户始终转发到同一台机器 | 简单但有单点风险,某台挂掉则 Session 丢失 |
| Session 复制 | 各服务器间同步 Session | 消耗网络带宽,节点多时性能差 |
| 集中式 Session(推荐) | 所有 Session 存入 Redis | ✅ 主流方案,弹性伸缩,节点故障不影响 |
| 无状态 JWT | 不再需要服务端存 Session | 彻底解决分布式问题,但引入 JWT 的其他问题 |
❗ 面试题:多服务器部署时 Session 怎么处理?
标准答案是用 Redis 集中存储 Session,所有服务节点从同一个 Redis 读取 Session 数据。
安全性:Session 服务端存储 > Cookie 客户端存储
存储类型:Session 支持任意对象 > Cookie 仅支持字符串
存储大小:Session 远大于 Cookie 的 4KB
生命周期:
session-timeout、PHP 的 session.gc_maxlifetime)。浏览器关闭只丢失了 Session ID 这个”钥匙”,Session 数据本身还会在服务器保留一段时间直到 GC 回收。这是现代 Token 认证的标准模式:
1 | sequenceDiagram |
为什么需要两个 Token? 职责分离:
当用户同时发起多个请求时,如果 Access Token 恰好过期,不能每个请求都去刷新 Token。标准做法是:
1 | import axios from 'axios' |
通俗理解:这相当于”排队机制”——第一个请求发现过期了,就先去”取新令牌”;其他请求在窗口等着,等第一个拿回新令牌后,大家继续办业务。
| 方案 | 安全风险 | 实际应用 |
|---|---|---|
| localStorage | XSS 直接泄露 | 最常见但也最危险 |
| Cookie(HttpOnly + SameSite) | XSS 安全 ✅,但跨域麻烦 | 同域下的 SPA |
| 内存(变量)+ Refresh Cookie | ✅ 刷新丢失 Access Token,但 Refresh Token 在 Cookie 中安全 | 最佳实践 |
JWT(JSON Web Token,读作 “jot”)是一种规范化的 Token 格式,定义在 RFC 7519。相当于”会自己说话的工牌”——不用去后台查数据库,看工牌本身就知道你是谁。
JWT 由三个用 . 分隔的 Base64URL 字符串组成:
1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c |
三部分分别是:
1 | { |
alg:签名算法(HS256、RS256 等)typ:类型,固定为 JWT1 | { |
iss(签发人)、sub(主题)、aud(受众)、exp(过期时间)、iat(签发时间)等1 | HMACSHA256( |
签名的作用:防止数据篡改。服务端收到 JWT 后,用同样的 secret 对 header+payload 重新签名,对比是否一致。
通俗理解:JWT 像一张”防伪标签”——你可以看到上面的字(payload),但你想改上面的字,签名就对不上了,会被发现。
1 | sequenceDiagram |
| 算法 | 类型 | 密钥 | 场景 |
|---|---|---|---|
| HS256 | 对称加密 | 同一密钥签名和验签 | 单体应用、认证和业务服务在一起 |
| RS256 | 非对称加密 | 私钥签名,公钥验签 | 微服务(认证服务独立)、第三方信任 |
JWT 无状态=无法从服务端主动使其失效。解决方案:
| 方案 | 说明 | 优缺点 |
|---|---|---|
| 客户端删除 | 前端删除本地 JWT | 简单,但 JWT 在有效期内仍然可用(游离态) |
| 黑名单 | 维护一个”提前注销”的 JWT 列表 | ✅ 实用,黑名单通常很小(只维护未过期但需要注销的) |
| 短有效期 | 设置短的过期时间(如 15 分钟) | 配合 Refresh Token,即使无法注销,影响窗口也小 |
| 修改用户密钥 | 用户注销时修改其在服务端的 secret | 使之前签发的所有 JWT 失效,但会使所有”已登录”用户重新登录 |
❗ 最佳实践:短有效期 + 黑名单(只维护未过期的已注销 Token)+ Refresh 联动。
| 防御措施 | 说明 |
|---|---|
| HTTPS | 传输层加密,防止中间人窃取 |
| 短有效期 | 即使被盗,窗口期很短 |
| 客户端指纹 | 生成 JWT 时绑定客户端特征(如 User-Agent、IP),被盗后无法在其他环境使用 |
| 存储在 Cookie 中并设置 HttpOnly | 防止 XSS 窃取 |
| Refresh Token 轮换(Rotation) | 每次使用 Refresh Token 都发放一个新的,旧的立即失效 |
| 攻击类型 | 原理 | 防御 |
|---|---|---|
| “none” 算法攻击 | 攻击者将 alg 改成 none,服务端若未禁用 none 算法则会跳过签名验证 | 服务端必须禁用 none 算法 |
| 算法混淆攻击 | 服务端期望 RS256(非对称),但攻击者用 HS256(对称),用已知的公钥作为 secret 签名 | 固定算法类型,或始终使用非对称加密 |
| 密钥暴力破解 | 使用弱密钥的 HS256 可能被暴力破解 | 使用强密钥,优先 RS256 |
不适合的场合:
适合的场合:
| 对比维度 | Session Cookie | JWT |
|---|---|---|
| 状态存放 | 服务端 | 客户端 |
| 伸缩性 | 需统一 Session 存储(Redis) | 天然支持,任意节点可验签 |
| 注销能力 | ✅ 服务端可直接删除 Session | ❌ 需黑名单或短有效期 |
| CSRF | ❌ 需额外防护 | ✅ 天然防御 |
| 跨域 | ❌ 受 Cookie 同源限制 | ✅ 不受限 |
| 实时性 | ✅ 可随时修改或撤销 | ❌ 修改权限后需等待 Token 过期 |
| 额外查询 | 每次需要查 Session | ❌ 不需要,但载荷过大影响传输效率 |
一次登录,全网通行。你在公司内部系统中只需登录一次,就可以访问 HR 系统、代码仓库、日志平台等所有内部系统。
1 | sequenceDiagram |
OAuth 2.0 的本意是授权(Authorization)——允许第三方应用在用户授权下访问用户在其他平台的数据。最常见的应用场景是”使用微信/Google 账号登录”。
| 角色 | 现实类比 | 例子 |
|---|---|---|
| Resource Owner(资源所有者) | 你本人 | 用户 |
| Client(客户端) | 想借你书的同学 | 第三方应用(”来记账” App) |
| Authorization Server(授权服务器) | 图书馆管理员 | 微信/Google 认证服务 |
| Resource Server(资源服务器) | 图书馆书库 | API 服务器(存储用户数据) |
| 模式 | 安全等级 | 适用场景 |
|---|---|---|
| 授权码模式(Authorization Code) | ⭐⭐⭐⭐⭐ | 最常用,有后端的 Web 应用 |
| 隐式模式(Implicit)— 已弃用 | ⭐⭐ | 纯前端 SPA(不再推荐,用 PKCE 替代) |
| 密码模式(Password) | ⭐⭐ | 高度信任的第一方应用(如自家 App) |
| 客户端凭证模式(Client Credentials) | ⭐⭐⭐⭐ | 服务间调用(无用户参与) |
1 | sequenceDiagram |
为什么需要授权码这个中间步骤?
因为 Access Token 不能暴露在浏览器——授权码是一次性的,由后端服务器凭 client_secret 去换取 Token。这样即使恶意脚本截取了授权码,没有 client_secret 也换不到 Token。
纯前端应用(SPA、移动 App)无法安全保存 client_secret,因此有了 PKCE 扩展:
1 | sequenceDiagram |
| 对比维度 | OAuth 2.0 | OpenID Connect (OIDC) |
|---|---|---|
| 目的 | 授权(允许访问资源) | 认证(确认身份)+ 授权 |
| 产出 | Access Token | Access Token + ID Token(JWT 格式) |
| 用户身份 | 不标准化,需要额外 API 获取 | 标准化的 JWT 包含用户信息 |
| 协议层级 | 基础协议 | OAuth 2.0 之上的认证层 |
通俗理解:OAuth 2.0 是”我给你一把钥匙,你可以进我的储物间”;OIDC 是”我不仅给你钥匙,还给你一张身份证,证明你确实是你”。
你可以理解为:OAuth 解决”你能做什么”(授权),OpenID 解决”你是谁”(认证)。
按面试出现频率排列,方便快速复习:
Cookie、localStorage、sessionStorage 的区别?
Session 和 JWT 的区别?各有什么优缺点?
JWT 由哪几部分组成?如何保证不被篡改?
Token 过期如何处理?Refresh Token 的作用?
如何防止 Token 被盗?
SSO 的实现原理?
OAuth 2.0 授权码流程是怎样的?为什么需要授权码?
SameSite Cookie 解决了什么问题?
前端如何安全地存储 Token?
OIDC 和 OAuth 2.0 的关系?
什么是 PKCE?为什么移动端需要它?
JWT 中的 “none” 算法攻击?
用一句话串联全文:
Cookie 是浏览器”帮你带”纸条,所以有 CSRF 风险;localStorage 是你”自己放”纸条,所以有 XSS 风险;Session 是服务端记小本本,有状态但好注销;JWT 是把小本本的内容印在工牌上,无状态但难回收;它们组合起来加上OAuth 2.0 和 SSO,就构成了前端鉴权的完整拼图。
最后更新:2026 年 6 月 · 前端鉴权知识点终稿
只是用户看到仅仅只是浏览器本身,却很少能看到浏览器最核心的部分—浏览器内核。从第一款 libwww(Library WorldWideWeb)浏览器发展至今已经经历了无数竞争与淘汰了。现在国内常见的浏览器有:IE、Firefox、QQ 浏览器、Safari、Opera、Google Chrome、百度浏览器、搜狗浏览器、猎豹浏览器、360 浏览器、UC 浏览器、遨游浏览器、世界之窗浏览器等。但目前最为主流浏览器有五大款,分别是 IE、Firefox、Google Chrome、Safari、Opera。
AJAX 技术使开发者能够专注于互联网中数据的传输,而不再拘泥于数据传输的载体。通过它,我们获取数据的方式变得更加灵活,可控和优雅。但 AJAX 技术并不是一把万能钥匙,互联网中的数据隐私和数据安全(例如银行账号和密码)非常重要,为了保护用户数据的隐私与安全,浏览器使用同源策略限制了 AJAX 技术获取数据的范围和能力。但有时我们不得不想办法绕过同源策略,实现跨域请求资源。因此跨域技术一直成为开发者们经久不衰的讨论话题。
DNS(Domain Name System,域名系统)是互联网最重要的基础设施之一,它负责将人类可读的域名转换为机器可识别的 IP 地址。本文将从基础到进阶,全面讲解 DNS 的工作原理、记录类型及安全机制。
CDN(Content Delivery Network,内容分发网络)是现代互联网基础设施的重要组成部分。本文将从概念到实践,全面讲解 CDN 的工作原理、关键技术及应用场景。
想象你去一家餐厅吃饭:
这就是 PWA(Progressive Web Application,渐进式网页应用)——把 Web 的”随手可得”和 Native App 的”好用能力”结合在一起。
PWA 不是一门新技术,而是一组技术的组合,核心有三:
| 技术 | 作用 | 类比 |
|---|---|---|
| Web App Manifest | 让网页可安装到桌面 | 给网页一个”身份证” |
| Service Worker | 离线缓存 + 消息推送 + 网络代理 | 浏览器背后的”隐形管家” |
| Web Push | 服务器向用户推送通知 | 餐厅服务员来通知你 |
❗ 面试常问:PWA 和 Native App 相比的优缺点?
✅ 优点:无需安装、即时更新、可被搜索引擎索引、跨平台、体积极小
❌ 缺点:无法访问部分原生 API(蓝牙、NFC 等)、iOS 支持有限、后台保活能力弱于原生
1 | 用户操作 PWA 能力 实现技术 |
PWA 的核心门槛是 HTTPS——Service Worker 只能在 HTTPS 下工作(本地调试的 localhost 除外)。没有 HTTPS,PWA 一切免谈。
manifest.json 是一个 JSON 文件,告诉浏览器:这个网站可以像一个原生应用一样被”安装”到用户设备上。
1 | <!-- 在 HTML 中引用 --> |
1 | { |
| 字段 | 说明 | 面试频率 |
|---|---|---|
start_url | 从桌面图标打开时显示的页面 | ⭐⭐ |
display | 显示模式:standalone(无浏览器栏,像 App)、fullscreen、minimal-ui、browser | ⭐⭐⭐ |
background_color | 启动时的背景色(在 Splash 屏显示) | ⭐ |
theme_color | 浏览器地址栏、任务栏的颜色 | ⭐ |
icons | 各分辨率的应用图标,至少 192x192 和 512x512 | ⭐⭐ |
scope | 哪些路径在 PWA 范围内,超出则用浏览器打开 | ⭐⭐ |
❗ 面试题:PWA 的可安装条件是什么?
- 有
manifest.json(包含name或short_name、icons、start_url、display)- 注册了 Service Worker
- 使用 HTTPS
- 用户有交互行为(不能一打开页面就弹安装提示)
1 | sequenceDiagram |
Service Worker(简称 SW) 是浏览器在后台独立运行的一个脚本,本质是一个 Web Worker,但它比普通 Web Worker 多了拦截网络请求和离线缓存的能力。
1 | graph LR |
通俗理解:Service Worker 像一个”交通警察”站在浏览器和网络之间——它可以决定”这个请求走缓存”还是”这个请求走网络”。
| 特性 | Web Worker | Service Worker |
|---|---|---|
| 目的 | 多线程计算 | 网络代理 + 离线缓存 |
| 生命周期 | 随页面关闭而结束 | 独立于页面,浏览器可唤醒/终止 |
| 可拦截请求 | ❌ | ✅ |
| 可离线使用 | ❌ | ✅ |
| 可推送通知 | ❌ | ✅ |
| 可访问 DOM | ❌ | ❌ |
| HTTPS 要求 | ❌ | ✅(localhost 除外) |
fetch 事件拦截所有网络请求1 | // 主线程中注册 |
关键点:
scope(作用域):/sw.js 默认作用域是 ./(即 sw.js 所在目录)。如果想扩大作用域,需要在注册时指定 { scope: '/' },并且服务端返回的 Service-Worker-Allowed 头需要允许该作用域load 事件后注册,避免与页面渲染竞争资源1 | // sw.js — Service Worker 脚本 |
Service Worker 配合 Cache Storage API 实现离线缓存。缓存策略的选择直接影响用户体验和新鲜度。
| 策略 | 行为 | 适用场景 |
|---|---|---|
| Cache First(缓存优先) | 有缓存直接用,没有就走网络 | 不常变的静态资源(CSS、JS 字体) |
| Network First(网络优先) | 先请求网络,失败就用缓存 | 需保持较新但可接受旧数据的场景(文章列表) |
| Stale-While-Revalidate(迂回策略) | 立即返回缓存,同时后台发起网络请求更新缓存 | 最常用,兼顾速度和新鲜度 |
| Network Only | 只走网络 | 实时数据(股票行情、聊天消息) |
| Cache Only | 只读缓存 | 预缓存资源(已确定不变的静态文件) |
1 | sequenceDiagram |
为什么 Stale-While-Revalidate 最好?——用户永远不会等待网络,同时资源又能及时更新。
1 | // sw.js |
1 | installing → installed (waiting) → activating → activated → redundant |
| 状态 | 触发条件 | 关键操作 |
|---|---|---|
| installing | SW 注册后触发 install 事件 | 预缓存静态资源 |
| installed (waiting) | install 完成,等待旧 SW 控制的页面关闭 | 可调用 self.skipWaiting() 跳过等待 |
| activating | 旧 SW 不再控制任何页面,触发 activate 事件 | 清理旧版本缓存 |
| activated | activate 完成,SW 开始拦截请求 | 可调用 self.clients.claim() 立即接管所有页面 |
| redundant | 被新 SW 替换,或安装失败 | 无 |
1 | stateDiagram-v2 |
1 | // sw.js |
当浏览器检测到 sw.js 有字节级差异时(哪怕一个空格变了),就会触发更新流程:
1 | sequenceDiagram |
**如果用了 skipWaiting()**:新 SW 安装后立即激活,但已打开的页面不会自动被接管——需要页面调用 navigator.serviceWorker.controller 变化后刷新,或在 activate 中调用 clients.claim()。
Workbox 是 Google 官方的 PWA 框架,封装了 Service Worker 的常见功能,让你不用手写 sw.js。配合 webpack 插件 workbox-webpack-plugin 可以自动化生成 SW 配置。
1 | npm install workbox-webpack-plugin --save-dev |
1 | // webpack.config.js |
| 方式 | 说明 | 适用场景 |
|---|---|---|
cdn | 从 Google CDN 引入 workbox 运行时 | ❌ 国内不可用 |
local | 插件在本地生成 workbox 代码,一起部署 | 项目发布时就确定了 |
disabled | 自己指定引入路径 | 推荐,可自建 CDN |
1 | sequenceDiagram |
1 | // 主线程 |
1 | // sw.js |
Web Push 使用 VAPID(Voluntary Application Server Identification) 协议,用于标识推送服务器:
applicationServerKey)PWA 的核心技术有哪些?
Service Worker 是什么?和 Web Worker 有什么区别?
Service Worker 的声明周期是怎样的?
skipWaiting() 跳过 waitingclients.claim() 立即接管页面缓存策略有哪些?分别适用于什么场景?
PWA 的可安装条件是什么?
如何更新 Service Worker 的缓存?
activate 中清理旧缓存 → clients.claim() 接管页面Web Push 推送的流程?
PWA 在 iOS 上的支持情况?
Workbox 的核心作用是什么?
1 | 用户访问你的网站 |
| 平台 | SW 支持 | 推送支持 | 安装支持 | 评价 |
|---|---|---|---|---|
| Chrome(Android) | ✅ 完整 | ✅ | ✅ | 最佳体验 |
| Safari(iOS) | ✅ 11.3+ | ❌ | ✅(有限) | 功能受限 |
| Firefox | ✅ | ✅ | ✅ | 完善 |
| Edge | ✅ | ✅ | ✅ | 完善 |
最后更新:2026 年 6 月 · PWA 知识点终稿