feat(pwa): wire up @ducanh2912/next-pwa + register SW in layout

PWA install flow was wired but unusable: pwaUtil.install() calls
deferred.prompt(), but Chrome only fires beforeinstallprompt when a
valid Service Worker is registered + a manifest is linked. The project
had both intent (manifest, usePwaInstall hook) but no live SW —
public/sw.js was a stale workbox build artifact from a previous
attempt with hardcoded chunk URLs that no longer matched any build.

What this commit does:

1. Add @ducanh2912/next-pwa@10.2.9 as devDependency.
2. Wrap nextConfig with withPWA({...}):
   - dest: "public" SW outputs to public/sw.js
   - disable: true skip SW generation in dev (HMR-friendly)
   - register: false don't auto-inject registration
   - workboxOptions.skipWaiting: true + clientsClaim: true — new SW
     takes over immediately
3. Add --webpack flag to dev/build/dev:proxy scripts.
   @ducanh2912/next-pwa is webpack-only; Turbopack (Next 16 default)
   doesn't load webpack plugins. Per user decision to accept the perf
   trade-off in exchange for a working PWA.
4. Delete stale public/sw.js (workbox will regenerate it at build
   time with the correct chunk URLs).
5. Add src/app/_components/core/sw-register.tsx: a no-UI client
   component that registers /sw.js in production. Mounted at the end
   of <body> in layout.tsx. disable: true means dev mode skips
   registration (no /sw.js to fetch anyway).

After this commit + pnpm build, public/sw.js is regenerated with
correct chunk URLs, registered on first prod load, and Chrome fires
beforeinstallprompt — usePwaInstall + pwaUtil.install() then trigger
the native install prompt end-to-end.
This commit is contained in:
2026-06-16 19:36:03 +08:00
parent e632fa7139
commit 2acc005809
6 changed files with 2333 additions and 21 deletions
+4 -3
View File
@@ -3,9 +3,9 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev:proxy": "HTTPS_PROXY=http://127.0.0.1:7891 next dev",
"build": "next build",
"dev": "next dev --webpack",
"dev:proxy": "HTTPS_PROXY=http://127.0.0.1:7891 next dev --webpack",
"build": "next build --webpack",
"start": "next start -p 9135",
"build:start": "npm run build && npm run start",
"lint": "eslint",
@@ -35,6 +35,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"@ducanh2912/next-pwa": "^10.2.9",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",