基于SvelteKit+Typescript的PWA无法在安卓Chrome/Brave浏览器触发安装提示的问题求助
大家好,我现在在做两个基于SvelteKit + TypeScript + Vite的PWA项目:一个是用来复现问题的最小示例simple-pwa,另一个是我的毕设项目Final-Year-Project,两个项目遇到了完全相同的问题,想请大家帮忙排查一下。
我的开发环境是MacOS,测试设备是安卓手机,用Chrome和Brave浏览器来测试PWA的安装功能。
已经完成的配置步骤
我知道PWA要具备可安装性,需要满足HTTPS服务和正确的manifest.json这两个核心要求,所以做了以下操作:
配置本地HTTPS服务
用mkcert生成了本地信任的SSL证书,步骤如下:brew install mkcert mkcert -install brew install nss mkcert <ip> localhost 127.0.0.1 ::1这里的
<ip>是运行npm run dev -- --host后终端输出的本地IP,这样就能通过HTTPS访问我的本地开发服务了,浏览器地址栏也显示连接是安全的。编写
manifest.json
我在项目里添加了包含必要字段的manifest.json,设置了display: standalone、start_url: /,还有多个不同尺寸的图标,具体内容如下:{ "id": "/", "name": "simple-pwa", "icons": [ { "src": "icons/icon.jpg", "type": "image/jpg", "sizes": "512x512" }, { "src": "icons/icon-144.png", "type": "image/png", "sizes": "144x144" }, { "src": "icons/icon-192.jpg", "type": "image/jpg", "sizes": "192x192" } ], "description": "Test", "display": "standalone", "start_url": "/", "screenshots": [ { "src": "icons/icon.jpg", "type": "image/jpg", "sizes": "512x512", "form_factor": "wide" }, { "src": "icons/icon.jpg", "type": "image/jpg", "sizes": "512x512", "form_factor": "narrow" } ] }配置Service Worker
为了实现离线访问,我添加了Service Worker,参考了MDN的PWA教程和相关示例代码,实现了安装时缓存静态资源、激活时清理旧缓存、fetch请求时网络优先缓存兜底的逻辑,代码如下:/// <reference types="@sveltejs/kit" /> /// <reference no-default-lib="true"/> /// <reference lib="esnext" /> /// <reference lib="webworker" /> const sw = /** @type {ServiceWorkerGlobalScope} */ ( /** @type {unknown} */ (self) ); import { build, files, version, prerendered } from "$service-worker"; // Create a unique cache name for this deployment const CACHE = `cache-${version}`; console.log(`Current version: ${CACHE}`); const ASSETS = [ ...build, // the app itself ...files, // everything in `static` ...prerendered, ]; sw.addEventListener("install", (event) => { event.waitUntil(async () => { console.log("Cashing assets."); const cache = await caches.open(CACHE); await cache.addAll(ASSETS); }); }); sw.addEventListener("activate", (event) => { event.waitUntil( caches.keys().then(async (keys) => { // delete old caches for (const key of keys) { if (key !== CACHE) await caches.delete(key); } }), ); }); sw.addEventListener("fetch", (event) => { async function respond() { const url = new URL(event.request.url); const cache = await caches.open(CACHE); // `build`/`files` can always be served from the cache if (ASSETS.includes(url.pathname)) { const response = await cache.match(url.pathname); if (response) { return response; } } // for everything else, try the network first, but // fall back to the cache if we're offline try { const response = await fetch(event.request); // if we're offline, fetch can return a value that is not a Response // instead of throwing - and we can't pass this non-Response to respondWith if (!(response instanceof Response)) { throw new Error("invalid response from fetch"); } if (response.status === 200) { cache.put(event.request, response.clone()); } return response; } catch (err) { const response = await cache.match(event.request); if (response) { return response; } // if there's no cache, then just error out // as there is nothing we can do to respond to this request throw err; } } event.respondWith(respond()); });
当前遇到的问题
- 第一次在安卓浏览器打开HTTPS地址时,能正常看到安装提示,安装后也能在系统里找到
simple-pwa的图标,杀掉本地dev服务后还能离线访问,这说明基础配置是有效的。 - 但是,当我卸载PWA后重新打开这个网页,或者关闭网页后再次打开时,安装提示再也不会自动出现了,而且手动点击浏览器右上角的三点菜单,也找不到“安装应用”的选项。
我已经排查了这些点:
- 浏览器地址栏显示连接是安全的,HTTPS配置正常;
- Chrome DevTools的Application->Manifest里能看到完整的manifest信息,没有报错;
- Service Worker注册成功,缓存的资源也正常;
- 已经确认浏览器没有禁用PWA相关的设置。
想请大家帮忙看看,可能是哪里出了问题?比如manifest.json有没有遗漏的必填字段?Service Worker的逻辑会不会影响安装提示的触发?或者本地HTTPS的配置有没有什么隐藏的坑?
内容来源于stack exchange

