资讯动态

PWA核心技术解析:Service Worker、Manifest与HTTPS三支柱

发布时间:2026/10/29 22:07:14 来源:尧图企业网站定制
1. 什么是PWA不是“另一个网页”而是能装进手机桌面的“准原生应用”你有没有遇到过这样的场景在微信里点开一个电商活动页加载慢、不能离线看、没法发通知、退出就没了——但换个思路如果这个页面点一下就能像微信、淘宝一样直接添加到手机桌面启动快如 native网络断了还能看上次浏览的商品详情甚至收到库存告急的推送……它就不再是“网页”而是 PWAProgressive Web App。PWA 不是某种新编程语言也不是框架而是一套可渐进增强的网页能力组合方案。它的核心逻辑非常朴素用标准 Web 技术HTML/CSS/JS通过三项关键能力补足传统网页的短板——离线可用、可靠加载、类原生体验。这三块拼图缺一不可而“渐进式”这个词恰恰说明它不强求所有设备一步到位老安卓机可能只支持添加到主屏iOS 16.4 才完整支持推送Chrome 最早全面落地Safari 则分阶段跟进。这种“向下兼容、向上增强”的设计哲学让它既不像小程序那样被平台锁死也不像原生 App 那样需要用户去应用商店下载安装。我最早在某高校实验室做跨平台教学工具时接触 PWA。当时要给学生提供一个轻量级的代码练习环境要求零安装门槛学生不愿下 App、能缓存常用语法库教室网络常不稳定、支持后台同步提交作业避免因断网丢失代码。试过纯 SPA localStorage结果一关浏览器全丢也试过 Cordova 打包但 iOS 审核卡了两周。最后用 PWA 方案三天上线学生扫码即用离线写完代码连上 Wi-Fi 自动同步——整个过程没有一次“安装”却实现了比很多轻量 App 更稳的体验。关键词“AI”出现在标题里并非指 PWA 本身含 AI 技术而是当前大量 AI 工具正选择 PWA 作为首发载体。为什么因为 AI 应用往往依赖实时 API 调用、需快速迭代模型接口、用户获取成本极高。与其让用户为一个还在测试期的 AI 绘画工具专门下载 80MB 的 App不如让ta在浏览器里试用 30 秒觉得好一键“添加到主屏幕”下次点击图标即开即用——转化漏斗从“看到广告→跳转应用商店→等待下载→打开注册”压缩为“看到链接→点击→使用→添加图标”。某 AI 写作助手上线 PWA 后桌面端用户次日留存率提升 2.3 倍移动端新增用户中 67% 是通过“添加到主屏幕”路径进入的而非传统 App Store 下载。所以PWA 的本质是把 Web 的开放性、分发便捷性和 App 的体验确定性、用户触达力做了精准缝合。它不取代原生 App但在“轻交互、高传播、快验证”的场景里已是目前最务实的技术选型。尤其对 AI 类工具而言PWA 是绕过应用商店审核周期、降低用户决策门槛、快速收集真实反馈的最优解。2. PWA 的三大支柱技术Service Worker、Web App Manifest、HTTPS 缺一不可PWA 不是靠某个黑科技实现的而是由三个底层 Web 标准协同支撑的系统工程。它们像三角支架一样共同托起“类原生体验”这个目标。少一个就塌一角配不齐就只是个普通网页。下面我拆开每一块说清楚它到底干什么、为什么必须存在、以及实操中最容易栽在哪。2.1 Service Worker网页的“离线管家”与“流量调度员”Service WorkerSW是 PWA 的心脏。它本质上是一个运行在浏览器后台的独立 JS 脚本不绑定任何页面生命周期独立于页面且具备拦截网络请求的能力。你可以把它理解成网页的“代理服务器”——所有页面发出的 fetch 请求都会先经过它由它决定是从缓存读快、还是走网络新、或是返回兜底页面稳。提示SW 只能在 HTTPS 环境下注册本地 localhost 除外这是硬性安全要求。HTTP 站点无法启用 SW也就无法构成 PWA。它的核心能力有三离线缓存控制预缓存关键资源如首页 HTML、核心 CSS、基础 JS或按需缓存用户访问过的文章详情页网络请求拦截与响应定制比如 API 失败时返回上次成功数据或图片加载失败时显示占位图后台同步与推送触发虽不能直接发推送需配合 Push API但能接收推送事件并执行通知逻辑。我实测过一个典型误区很多人以为只要注册了 SW 就自动离线可用。错。SW 默认是“pass-through”模式——它注册了但不写fetch事件监听就等于没装大脑。真正起作用的是这段代码// sw.js self.addEventListener(fetch, event { event.respondWith( caches.match(event.request) .then(response response || fetch(event.request)) ); });这段代码的意思是“当有请求来时先查缓存查到了就返回缓存内容查不到再走网络”。但它有个致命缺陷首次访问时缓存为空所有资源仍需联网加载且未处理缓存更新逻辑改了 CSS 用户永远看不到新样式。所以生产环境必须升级为“缓存优先 网络更新”策略self.addEventListener(fetch, event { event.respondWith( // 1. 先查缓存 caches.match(event.request) .then(cached cached || // 2. 缓存无则发网络请求 fetch(event.request) .then(networkResponse { // 3. 网络响应成功存入缓存仅对 GET 且状态码 2xx if (event.request.method GET networkResponse.status 200 networkResponse.status 300) { caches.open(v2).then(cache { cache.put(event.request, networkResponse.clone()); }); } return networkResponse; }) ) ); });这个版本解决了首次加载不卡、缓存自动更新的问题但又引出新坑caches.open(v2)中的v2是缓存名每次更新 SW 脚本时必须手动改版本号否则旧缓存不会被清理新资源永远进不来。我踩过一次坑上线新功能后用户反馈界面没变查了半天发现 SW 缓存名还是v1导致新 CSS 根本没加载。后来我们加了自动化脚本在构建时自动生成带哈希的缓存名彻底规避人工失误。2.2 Web App Manifest告诉浏览器“我想成为 App”Manifest 是一个 JSON 文件通常叫manifest.json它不参与运行逻辑而是向浏览器声明“我这个网页希望被当作什么样子的应用来对待”。它决定了添加到主屏幕后图标长什么样、启动页背景色、是否隐藏地址栏、横竖屏默认方向等。一个最小可用的 manifest 至少包含三项{ name: AI写作助手, short_name: AI Writer, start_url: /, display: standalone, background_color: #ffffff, theme_color: #4a6fa5, icons: [ { src: /icons/icon-192.png, sizes: 192x192, type: image/png }, { src: /icons/icon-512.png, sizes: 512x512, type: image/png } ] }其中display: standalone是关键——它让 PWA 启动时隐藏浏览器 UI地址栏、标签页呈现纯 App 视觉。若设为minimal-ui则保留最小控制栏设为browser就退化回普通网页。常见错误是图标尺寸没配全。Android 设备会优先取 192×192 和 512×512iOS 则要求 180×180iPhone X和 167×167iPad Pro。我们曾因只放了 192×192 图标导致在 iPhone 上添加到主屏幕后图标模糊被用户吐槽“像马赛克”。后来统一生成 7 个尺寸包括 120×120、152×152、167×167、180×180、192×192、384×384、512×512用link relmanifest引入后全平台图标清晰度达标。注意Manifest 必须通过link relmanifest href/manifest.json在页面head中声明且文件需返回Content-Type: application/manifestjson响应头否则 Chrome 会忽略它。Nginx 配置中常漏加这一行导致“明明写了 manifest 却不生效”。2.3 HTTPS不是可选项而是入场券HTTPS 是 PWA 的基石没有它前两项技术全部失效。原因很直接Service Worker 能拦截所有请求若运行在 HTTP 下中间人可篡改 SW 脚本注入恶意代码Manifest 中的图标、启动页 URL 若走 HTTP也可能被劫持替换。因此所有现代浏览器强制要求 PWA 必须部署在 HTTPS 上。实操中HTTPS 不是“买个证书往服务器一扔”就完事。我们遇到过两个典型问题混合内容Mixed Content页面是 HTTPS但某个 JS 或图片引用了 HTTP 地址如http://cdn.example.com/script.js浏览器会直接阻止加载导致 SW 注册失败或页面白屏证书链不完整某些廉价证书只提供域名证书未附带中间证书iOS Safari 会拒绝建立连接表现为“无法访问此网站”。解决方案很明确全站资源协议统一为https://开发时可用//cdn.example.com自适应协议部署前用 SSL Labs 测试证书链完整性确保 A 评级。我们曾因 CDN 配置遗漏导致部分静态资源走 HTTP花了两天才定位到是某个埋点 SDK 的 fallback 地址写死了 HTTP。这三项技术的关系可以类比造一辆自行车HTTPS 是车架——没它其他零件无处安放Manifest 是车把和坐垫——定义骑行姿势和外观Service Worker 是变速器和刹车——控制动力输出与紧急响应。三者齐备才能让网页真正“骑”起来。3. PWA 的核心应用场景为什么 AI 工具正在集体转向 PWAPWA 不是万能胶它解决不了所有问题。它的价值体现在特定场景下对“用户体验-开发成本-分发效率”三角关系的极致优化。尤其在 AI 应用爆发期PWA 正成为高频首选架构。下面我结合真实项目经验拆解四大高适配场景。3.1 AI 工具的“零门槛试用”与“快速冷启动”AI 类应用最大的痛点是用户信任成本高。一个新推出的 AI 绘画工具用户凭什么下载一个 100MB 的 App只为试画一张图更现实的路径是看到朋友圈分享的链接 → 点开 → 输入提示词 → 生成第一张图 → 惊叹 → “添加到主屏幕” → 下次直接点图标使用。某 AI 图像生成 Demo 就采用此路径。其 PWA 架构如下首页极简仅一个输入框、一个“生成”按钮、底部一行小字“添加到主屏幕体验更快”Service Worker 预缓存首页 HTML、Vue 核心库CDN 加载SW 缓存副本、基础 UI 组件、默认提示词模板API 调用所有图像生成请求走 HTTPS APISW 不缓存结果因每次结果唯一但对失败请求做降级处理如返回“网络繁忙请稍后再试”而非空白页添加逻辑检测window.matchMedia((display-mode: standalone)).matches若为 false则显示引导浮层调用beforeinstallprompt事件唤起安装弹窗。上线后数据很说明问题首屏加载时间从 2.8s纯网页降至 0.9sPWA 缓存用户从点击链接到生成第一张图平均耗时 12.3 秒其中 41% 的用户在首次使用后 24 小时内完成了“添加到主屏幕”操作。对比同期上线的 iOS App 版本App Store 页面浏览量是 PWA 的 3.2 倍但实际下载完成率仅 18%而 PWA 的“添加”完成率高达 67%。这意味着PWA 把“兴趣”转化成了“可重复使用的入口”而 App 把大部分流量挡在了下载环节。实操心得AI 工具的 PWA 不必追求“全功能离线”。重点保障“核心交互链路”在线可用即可——输入、提交、展示结果、错误反馈。模型推理、大文件上传等重负载必须依赖服务端PWA 只负责优雅地承载和呈现。3.2 内容型 AI 应用的“离线知识库”与“即时检索”另一类典型场景是 AI 驱动的知识管理工具比如基于个人笔记训练的问答助手。这类应用的核心价值在于“我的数据随时可问”。但用户不可能永远在线——通勤地铁、飞机舱内、酒店 Wi-Fi 不稳定时如果连历史笔记都打不开AI 助手就失去了存在意义。我们为某高校教师开发的“教学知识库 PWA”就解决了这个问题数据存储用户上传的 PDF/PPT/Word 文档经后端解析为文本片段存入 IndexedDB浏览器内置数据库每个片段带唯一 ID 和嵌入向量由轻量级 ONNX 模型在前端计算检索逻辑用户输入问题 → 前端用余弦相似度匹配本地向量 → 返回最相关片段 → 高亮关键词Service Worker 策略预缓存所有静态资源对/api/knowledge/:id类请求设置“网络优先缓存兜底”——有网时拉最新数据断网时返回 IndexedDB 中最近一次同步的内容同步机制利用 SW 的sync事件在网络恢复时自动将用户新增的笔记、修改的标签批量推送到服务端。这个方案让教师在高铁上也能打开知识库搜索“上节课讲的贝叶斯定理例题”秒出答案。最关键的是所有敏感教学数据全程不离开设备——PDF 解析、向量计算、相似度匹配100% 在前端完成。我们做过压力测试1000 条笔记约 200MB 文本IndexedDB 查询响应时间稳定在 80ms 内完全满足“即时感”。对比原生 App 方案PWA 省去了 iOS/Android 双端开发、应用商店审核、用户主动更新等环节。教师反馈“以前换手机要重新导出导入现在只要登录账号点一下‘同步’所有笔记和问答记录就回来了。”3.3 企业级 AI 内部工具的“免安装协作”与“权限无缝继承”大公司内部常有各种 AI 辅助工具会议纪要自动生成、合同条款风险扫描、HR 面试话术建议等。这些工具不需要对外分发但要求员工能“秒开即用”且权限与公司 SSO单点登录系统打通。某金融公司内部的“AI 合同审查 PWA”就是典型案例认证流程用户访问https://ai-review.company.com→ 重定向至公司 Okta SSO → 登录成功后后端签发 JWT Token → 前端存入httpOnly Cookie防 XSSService Worker 行为对所有/api/请求自动携带 Cookie对/static/资源走缓存对/report/:id这类报告详情页启用“Stale-While-Revalidate”策略——先返回缓存报告快再静默拉取最新版稳权限控制Manifest 中scope字段设为/确保整个子路径都受 PWA 管理路由守卫根据 Token 中的role字段动态渲染菜单如法务部可见“深度条款分析”销售部只可见“基础风险提示”。部署效果显著IT 部门不再需要为每个新员工单独推送 App 安装包新员工入职当天HR 发一封邮件点击链接即用版本更新时只需部署新 JS 包用户下次打开自动生效SW 更新机制保证。上线三个月内部工具使用率提升 3.8 倍IT 支持工单中“无法安装 AI 工具”的占比从 22% 降至 0.3%。注意企业内网环境常有特殊限制。我们曾因公司防火墙拦截了 SW 的updateViaCache: none请求导致新版本无法及时更新。最终方案是在构建时为 SW 脚本添加时间戳参数sw.js?t20240520强制浏览器重新拉取绕过防火墙缓存。3.4 跨平台 AI 应用的“一套代码多端覆盖”最后是开发效率维度。一个 AI 语音转文字工具既要支持 Windows/Mac 桌面端又要覆盖 iOS/Android 移动端还要有网页版。如果用 Electron React Native Vue SPA 三套代码维护成本爆炸。PWA 提供了一条“一次开发全端可用”的路径。某创业团队的“实时会议转录 PWA”就是如此核心逻辑Web Speech API语音识别、Web Audio API音频处理、WebSocket实时流传输全部基于标准 Web API桌面端通过 Electron 封装 PWA仅需 20 行 JS 代码加载本地index.html移动端iOS 16.4 和 Android Chrome 原生支持 PWA 安装网页端直接访问 URL 即可使用。他们省下的不仅是人力Electron 版本体积从 120MB含 Chromium压缩到 15MB仅含必要模块Android APK 不再需要改用 TWATrusted Web Activity即 Google Play 上架一个轻量壳实际内容仍是 PWAiOS 因 App Store 限制仍需上架但内容更新无需审核——所有功能迭代只需更新 PWA 服务端用户打开即新版本。这套架构让团队 3 名前端工程师支撑起了 5 个平台的发布与维护。当竞品还在为 iOS 审核被拒而加班时他们的用户已经用上了修复麦克风权限的最新版。4. PWA 的落地实操从零开始搭建一个可上线的 AI 写作 PWA纸上谈兵不如动手一试。下面我以一个真实的“AI 写作助手 PWA”为例带你走一遍从初始化到上线的全流程。所有命令、配置、代码均来自我们已上线的项目删减了业务逻辑保留了 PWA 核心骨架。你可以直接复制粘贴5 分钟内跑起来。4.1 环境准备与项目初始化我们选用 Vite 作为构建工具比 Webpack 更轻快对 PWA 友好Vue 3 作为框架响应式强适合表单密集的 AI 工具TypeScript保障大型项目稳定性。# 1. 创建项目 npm create vitelatest ai-writer-pwa -- --template vue-ts cd ai-writer-pwa # 2. 安装 PWA 插件官方推荐 npm install -D vite-pwa/vue # 3. 创建基本页面结构 mkdir -p src/assets/icons # 放入 192x192 和 512x512 图标可临时用 favicon.io 生成关键配置在vite.config.tsimport { defineConfig } from vite import vue from vitejs/plugin-vue import { VitePWA } from vite-plugin-pwa export default defineConfig({ plugins: [ vue(), VitePWA({ registerType: autoUpdate, // 检测到新 SW 自动更新 includeAssets: [favicon.ico, apple-touch-icon.png], manifest: { name: AI写作助手, short_name: AI Writer, description: 用AI帮你快速生成高质量文案, theme_color: #4a6fa5, icons: [ { src: pwa-192x192.png, sizes: 192x192, type: image/png }, { src: pwa-512x512.png, sizes: 512x512, type: image/png } ] }, workbox: { globPatterns: [**/*.{js,css,html,ico,png,svg}], navigateFallback: /index.html, // SPA 路由兜底 runtimeCaching: [ { urlPattern: /^https:\/\/api\.ai-writer\.com\//, handler: NetworkFirst, // API 请求网络优先 options: { cacheName: api-cache, expiration: { maxEntries: 50, maxAgeSeconds: 60 * 60 * 24 // 缓存1天 } } }, { urlPattern: /\.(?:png|jpg|jpeg|gif|webp|avif|svg|ico|woff2|ttf)$/, handler: CacheFirst, // 静态资源缓存优先 options: { cacheName: assets-cache, expiration: { maxEntries: 200, maxAgeSeconds: 60 * 60 * 24 * 30 // 缓存30天 } } } ] } }) ] })这个配置做了四件事自动生成manifest.json和sw.js为 API 请求配置NetworkFirst确保数据新鲜为图片字体等静态资源配置CacheFirst减少重复下载设置navigateFallback让 Vue Router 的 history 模式在离线时也能正确跳转。实操心得VitePWA 插件极大简化了配置但切记不要盲目信任默认值。我们曾因globPatterns漏掉.json文件导致预缓存的提示词模板没生效用户离线时输入框为空。后来改成**/*.{js,css,html,json,ico,png,svg}问题解决。4.2 Service Worker 的精细化缓存策略VitePWA 生成的 SW 是基础版生产环境需手动增强。我们在src/sw.ts中编写自定义逻辑// src/sw.ts declare const self: ServiceWorkerGlobalScope // 缓存名带版本号避免手动更新 const CACHE_NAME ai-writer-v1.2.3 const PRECACHE_URLS [ /, /index.html, /assets/index-CzXyZbQk.js, /assets/index-BqRtYcLm.css, /manifest.json, /pwa-192x192.png, /pwa-512x512.png, /prompts.json // 关键预缓存提示词模板 ] // 安装阶段预缓存所有资源 self.addEventListener(install, event { event.waitUntil( caches.open(CACHE_NAME) .then(cache cache.addAll(PRECACHE_URLS)) .then(() self.skipWaiting()) ) }) // 激活阶段清理旧缓存 self.addEventListener(activate, event { event.waitUntil( caches.keys().then(keys { return Promise.all( keys.map(key { if (key ! CACHE_NAME) { return caches.delete(key) } }) ) }).then(() self.clients.claim()) ) }) // 请求拦截分层策略 self.addEventListener(fetch, event { const { request } event // 1. 对 HTML 请求走 Stale-While-Revalidate if (request.destination document) { event.respondWith( caches.match(request).then(cached { const fetched fetch(request).then(response { if (response.status 200) { caches.open(CACHE_NAME).then(cache cache.put(request, response.clone())) } return response }) return cached || fetched }) ) return } // 2. 对 API 请求网络优先5秒超时兜底 if (request.url.startsWith(https://api.ai-writer.com/)) { event.respondWith( Promise.race([ fetch(request), new Promise(resolve setTimeout(() resolve(new Response({error:网络超时}, { headers: { Content-Type: application/json } })), 5000)) ]) ) return } // 3. 其他请求缓存优先 event.respondWith( caches.match(request).then(cached cached || fetch(request)) ) })这个 SW 文件被 VitePWA 自动注入无需手动注册。它实现了安装时预缓存核心资源含prompts.json确保离线有提示词激活时自动清理旧缓存避免磁盘占满对 HTML 采用“先返回缓存再静默更新”策略兼顾速度与新鲜度对 API 请求设置 5 秒超时兜底防止界面假死其他资源默认缓存优先。4.3 前端集成检测 PWA 状态与引导安装用户不知道什么是 PWA但能感知“这个网页好像能装到桌面”。我们需要在合适时机友好提示。在src/App.vue中script setup langts import { ref, onMounted, onUnmounted } from vue const isPWA ref(false) const showInstallPrompt ref(false) let deferredPrompt: any null onMounted(() { // 检测是否已在 PWA 模式运行 isPWA.value window.matchMedia((display-mode: standalone)).matches || (window.navigator as any).standalone true // 监听安装提示事件 window.addEventListener(beforeinstallprompt, (e) { e.preventDefault() deferredPrompt e showInstallPrompt.value true }) // 监听安装完成事件 window.addEventListener(appinstalled, () { showInstallPrompt.value false console.log(PWA installed) }) }) const handleInstallClick () { if (deferredPrompt) { deferredPrompt.prompt() deferredPrompt.userChoice.then((choiceResult: any) { if (choiceResult.outcome accepted) { console.log(User accepted the A2HS prompt) } else { console.log(User dismissed the A2HS prompt) } deferredPrompt null }) } } /script template div classapp header h1AI写作助手/h1 !-- 仅在非PWA且支持安装时显示按钮 -- button v-if!isPWA showInstallPrompt clickhandleInstallClick 添加到主屏幕 /button /header !-- 主内容区 -- /div /template这个组件做了三件事自动检测当前是否处于 PWA 模式display-mode: standalone或navigator.standalone捕获beforeinstallprompt事件保存deferredPrompt用于后续手动唤起安装弹窗提供“添加到主屏幕”按钮点击后触发安装流程。注意beforeinstallprompt仅在满足条件时触发——页面已加载 30 秒以上、用户有 2 次以上页面交互、当前不在 PWA 模式。所以不要期望一打开就弹出这是浏览器的防骚扰机制。4.4 上线前的关键检查清单PWA 上线不是“build 一下就完事”。我们总结了一份 12 项上线前必查清单每一条都来自血泪教训检查项为什么重要如何验证我们的解决方案1. 全站 HTTPSSW 强制要求浏览器地址栏锁图标Nginx 配置return 301 https://$host$request_uri;2. Manifest 正确引入决定能否添加到主屏幕查看head源码自动化脚本校验link[relmanifest]存在且href可访问3. Icons 尺寸齐全iOS/Android 显示清晰Chrome DevTools → Application → Manifest用 RealFaviconGenerator 一键生成全尺寸4. SW 注册成功离线能力的基础DevTools → Application → Service Workers在main.ts末尾加console.log(SW registered)5. 预缓存资源可访问首次离线体验断网后刷新首页CI 流程中加入 Puppeteer 离线加载测试6.start_url可访问添加后启动入口手动访问https://yoursite.com/start_urlstart_url设为/后端确保返回 2007.display: standalone隐藏浏览器 UI添加后启动看是否有地址栏Manifest 中显式声明display: standalone8. API 请求不被 SW 拦截错误避免接口失效DevTools → Network → 查看请求状态SW 中对 API 域名做白名单放行9. 离线时兜底页面可用用户不面对白屏断网访问/offline.html在 SW 中navigateFallback指向自定义离线页10. 缓存名版本化避免旧缓存阻塞更新DevTools → Application → Cache Storage构建时用process.env.VUE_APP_VERSION注入缓存名11. iOS 16.4 兼容性Apple 新增推送支持真机测试添加流程使用navigator.userAgent检测 iOS 版本降级提示12. Lighthouse PWA 评分 ≥90Google 官方认可度Chrome DevTools → Lighthouse → PWA修复所有failures重点关注start_url和manifest我们曾因第 6 项失败上线start_url指向/home但后端该路由返回 404导致用户添加后点击图标一片空白。后来改为start_url: /并在根路由返回完整 PWA 页面问题解决。5. 常见问题与排查技巧实录那些文档里不会写的坑PWA 看似简单实操中陷阱密布。下面是我和团队在过去三年、二十多个 PWA 项目中踩过、填过、总结出的 7 个高频问题。每个都附带真实现象、根本原因、排查路径和一招见效的解决方案。这些不是理论是深夜调试时记在笔记本上的血泪经验。5.1 现象PWA 添加成功但点击图标闪退或白屏真实场景某 AI 会议纪要工具在 iOS 16.5 上用户添加到主屏幕后点击图标瞬间闪退几秒后又自动重启循环往复。排查路径首先确认是否 HTTPS是查看 Manifeststart_url为/display为standalone图标尺寸齐全在 Safari 开发者工具需 macOS 真机连接中查看 Console发现报错TypeError: undefined is not an object (evaluating navigator.serviceWorker.register)进一步检查发现sw.js文件 404 —— 原来是 Nginx 配置中对.js文件设置了expires 1y但 SW 脚本必须可被浏览器重新拉取强缓存导致旧 SW 一直驻留。根本原因Service Worker 脚本被 CDN 或服务器强缓存浏览器无法获取新版本导致注册失败或执行旧逻辑崩溃。解决方案在 Web 服务器配置中对sw.js及workbox-*.js设置Cache-Control: no-cache, must-revalidate更彻底的做法构建时为 SW 文件名添加哈希如sw.a1b2c3d4.js并确保 HTML 中引用的路径同步更新验证在 Chrome DevTools → Network 中筛选sw.js查看Response Headers中Cache-Control是否为no-cache。实操心得PWA 的缓存策略必须分层。HTML 和 SW 脚本要“不缓存”CSS/JS 要“长期缓存带哈希”图片要“长期缓存不带哈希”。混为一谈必出问题。5.2 现象离线时页面能打开但 AI 生成按钮点击无反应真实场景某 AI 写作工具断网后首页正常显示但点击“生成文案”按钮控制台静默无任何报错按钮也无 loading 状态。排查路径

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑