From a347ce8baf1ce81e5f16eb5d67058d29eeaaf50d Mon Sep 17 00:00:00 2001 From: wait4xx Date: Sun, 25 Oct 2026 20:49:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(pwa):=20=E5=85=A8=E7=AB=99=20PWA=20?= =?UTF-8?q?=E5=8C=96=E2=80=94=E2=80=94manifest+Service=20Worker+=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E4=B8=89=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - manifest.webmanifest:standalone 双语描述、192/512/maskable 图标 (favicon.svg 经 sharp 直出) - sw.js 保守策略:HTML network-first(不比 ESA 边缘更激进,防双重 陈旧)+ install 预缓存 16 核心路由(SSG 全站 <1MB,全站离线可读) + /_astro|fonts|photos 不可变 cache-first + 评论 API/CMS 绕行 - BaseLayout:manifest+双 scheme theme-color+apple-touch-icon+一次性 SW 注册(controller 守卫×VT 不重跑双保险) - 踩坑入档:python 单线程 http.server 拖慢 16 并发预缓存,验收须等 缓存键数稳定(曾误判 install 未跑);allSettled 静默是调试黑洞, install 失败必须探针可见 验证: 离线导航 6 页全 200(预缓存 16 条 500ms 就绪);node tests/e2e.mjs 31/31 PASS;manifest/sw/图标三路由 200 Spec: none (PWA 基建:manifest+SW+图标,离线矩阵入档) Co-authored-by: GLM-5.3 --- public/icons/icon-192.png | Bin 0 -> 4032 bytes public/icons/icon-512.png | Bin 0 -> 22940 bytes public/icons/icon-maskable-512.png | Bin 0 -> 18588 bytes public/manifest.webmanifest | 16 +++++ public/sw.js | 90 +++++++++++++++++++++++++++++ src/layouts/BaseLayout.astro | 11 ++++ 6 files changed, 117 insertions(+) create mode 100644 public/icons/icon-192.png create mode 100644 public/icons/icon-512.png create mode 100644 public/icons/icon-maskable-512.png create mode 100644 public/manifest.webmanifest create mode 100644 public/sw.js diff --git a/public/icons/icon-192.png b/public/icons/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..160076fb02dcb8e89029f66ce7367f2a42648723 GIT binary patch literal 4032 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 literal 0 HcmV?d00001 diff --git a/public/icons/icon-512.png b/public/icons/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..780394e9866a3a8e63a10610209675470baf19b2 GIT binary patch literal 22940 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

U81nbC@qeCi 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 literal 0 HcmV?d00001 diff --git a/public/icons/icon-maskable-512.png b/public/icons/icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..36b37866ae345f792484806927eacc0d815515f9 GIT binary patch literal 18588 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 literal 0 HcmV?d00001 diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest new file mode 100644 index 0000000..ff8dda8 --- /dev/null +++ b/public/manifest.webmanifest @@ -0,0 +1,16 @@ +{ + "name": "wait4x", + "short_name": "wait4x", + "description": "wait4x 的个人博客:阅读、技术与摄影", + "lang": "zh-CN", + "start_url": "/", + "scope": "/", + "display": "standalone", + "background_color": "#191d23", + "theme_color": "#191d23", + "icons": [ + { "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" }, + { "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" }, + { "src": "/icons/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } + ] +} diff --git a/public/sw.js b/public/sw.js new file mode 100644 index 0000000..acfa60f --- /dev/null +++ b/public/sw.js @@ -0,0 +1,90 @@ +/* + * wait4x.online Service Worker — 静态站保守策略 + * 设计约束(改前必读): + * - HTML 走 network-first:站点是 SSG 但内容会更新,且上游还有 ESA 边缘缓存—— + * SW 不能比边缘更激进,否则"刷了缓存还有 SW 旧页"双重陈旧坑 + * - /_astro/*(内容哈希文件名)、字体切片、photos 为不可变资源:cache-first + * - Artalk 评论 API 与 /admin 完全绕过 SW(动态数据不缓存、CMS 走网络) + * - 无 precache(首访零负担);激活时清旧版本缓存 + */ +const VERSION = 'w4x-v2'; +// install 预缓存核心路由(SSG 全量 ~30 页 HTML,<1MB,换来全站离线可读; +// 列表由构建产物路由手工维护,新增顶层页时补一行) +const PRECACHE = [ + '/', '/archives/', '/gallery/', '/moments/', '/books/', '/opensource/', + '/about/', '/terminal/', + '/en/', '/en/archives/', '/en/gallery/', '/en/moments/', '/en/books/', + '/en/opensource/', '/en/about/', '/en/terminal/', +]; +const IMMUTABLE = [ + /\/_astro\//, // 构建产物(文件名带哈希) + /\/fonts?\//, // 字体切片(fontsource,内容不变) + /\/photos\//, // 图库压缩版(git 仓管理,变更=换文件) + /\/icons\//, // PWA 图标 + /\.(?:woff2|png|jpg|webp|svg|ico|css|js|webmanifest|xml)$/i, // 兜底静态后缀 +]; +const NEVER_CACHE = [/\/api\//, /\/artalk/, /\/admin/, /\/wp-/]; + +self.addEventListener('install', (e) => { + e.waitUntil( + (async () => { + const cache = await caches.open(VERSION); + const results = await Promise.allSettled(PRECACHE.map((u) => cache.add(new Request(u, { cache: 'reload' })))); + // 探针:install 失败原因必须可见(allSettled 静默是调试黑洞) + results.forEach((r, i) => { + if (r.status === 'rejected') console.error(`[sw-install] ${PRECACHE[i]} →`, r.reason); + }); + console.log(`[sw-install] done ok=${results.filter(r => r.status === 'fulfilled').length}/${PRECACHE.length} keys=${(await cache.keys()).length}`); + self.skipWaiting(); + })(), + ); +}); + +self.addEventListener('activate', (e) => { + e.waitUntil( + (async () => { + const keys = await caches.keys(); + await Promise.all(keys.filter((k) => k !== VERSION).map((k) => caches.delete(k))); + await self.clients.claim(); + })(), + ); +}); + +self.addEventListener('fetch', (e) => { + const req = e.request; + if (req.method !== 'GET') return; + const url = new URL(req.url); + if (url.origin !== self.location.origin) return; // 评论等三方资源不掺和 + if (NEVER_CACHE.some((re) => re.test(url.pathname))) return; + + if (req.mode === 'navigate') { + // HTML network-first:网络失败时回缓存(离线阅读兜底),成功时后台更新缓存 + e.respondWith( + (async () => { + const cache = await caches.open(VERSION); + try { + const fresh = await fetch(req); + if (fresh.ok) cache.put(req, fresh.clone()); + return fresh; + } catch { + const hit = await cache.match(req); + return hit || Response.error(); + } + })(), + ); + return; + } + + if (IMMUTABLE.some((re) => re.test(url.pathname))) { + e.respondWith( + (async () => { + const cache = await caches.open(VERSION); + const hit = await cache.match(req); + if (hit) return hit; + const res = await fetch(req); + if (res.ok && res.status === 200) cache.put(req, res.clone()); + return res; + })(), + ); + } +}); diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 33ec871..629742a 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -60,6 +60,17 @@ const withSlash = (p: string) => (p.endsWith('/') ? p : `${p}/`); {track === 'reading' && } + + + + + +