feat: integrate PWA support with @ducanh2912/next-pwa

Configure Progressive Web App capabilities for production builds, enabling offline support and installability. PWA is disabled in dev to avoid HMR conflicts, and switches the build to webpack since PWA tooling requires it.
This commit is contained in:
2026-06-10 13:18:26 +08:00
parent 2066934094
commit cd693b75ae
8 changed files with 2381 additions and 14 deletions
+23 -4
View File
@@ -1,13 +1,32 @@
import type { NextConfig } from "next";
import withPWAInit from "@ducanh2912/next-pwa";
/**
* PWA 开关:仅在 production 启用。
* - dev 模式 SW 会干扰 HMR
* - 测试/构建(vitest)也跳过
*/
const isProd = process.env.NODE_ENV === "production";
const withPWA = withPWAInit({
// SW 输出目录(Next.js 静态资源根)
dest: "public",
// 仅 production 注入;dev 不启用避免 HMR 干扰
disable: !isProd,
// 缓存策略:API 不缓存(业务 token 实时敏感),静态资源用默认 Workbox 策略
// 不显式声明 runtimeCaching,走 Workbox 默认(precache + NetworkFirst HTML + CacheFirst 静态)
});
/**
* Next.js 16 临时绕过 `/_global-error` prerender 的 workStore bug
* 标记根 layout 不参与静态预渲染(global-error 会在请求时渲染)
* https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
*/
const nextConfig: NextConfig = {
// Next.js 16 临时绕过 `/_global-error` prerender 的 workStore bug
// 标记根 layout 不参与静态预渲染(global-error 会在请求时渲染)
// https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
experimental: {
// 关闭静态优化以规避 16.2.7 global-error prerender bug
staticGenerationRetryCount: 0,
},
};
export default nextConfig;
export default withPWA(nextConfig);
+2 -1
View File
@@ -4,7 +4,7 @@
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"build": "next build --webpack",
"start": "next start",
"lint": "eslint",
"lint:fix": "eslint --fix",
@@ -14,6 +14,7 @@
"generate-barrels": "barrelsby --delete -c barrelsby.json"
},
"dependencies": {
"@ducanh2912/next-pwa": "^10.2.9",
"@fingerprintjs/fingerprintjs": "^5.2.0",
"@xstate/react": "^5",
"classnames": "^2.5.1",
+2319 -9
View File
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+20
View File
@@ -0,0 +1,20 @@
{
"name": "cozsweet",
"short_name": "cozsweet",
"description": "Cozsweet — Your exclusive AI companion",
"start_url": "/splash",
"scope": "/",
"display": "standalone",
"orientation": "portrait",
"background_color": "#0d0b14",
"theme_color": "#f84d96",
"lang": "en",
"icons": [
{
"src": "/favicon.ico",
"sizes": "any",
"type": "image/x-icon",
"purpose": "any"
}
]
}
+1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+15
View File
@@ -8,6 +8,21 @@ import { RootProviders } from "@/providers/root-providers";
export const metadata: Metadata = {
title: "cozsweet",
description: "cozsweet frontend (Next.js)",
// PWA:链接到 public/manifest.json(由 @ducanh2912/next-pwa 体系使用)
manifest: "/manifest.json",
// 浏览器顶栏 / Android PWA 顶栏颜色
themeColor: "#f84d96",
// iOS Safari "添加到主屏" 元数据
appleWebApp: {
capable: true,
statusBarStyle: "default",
title: "cozsweet",
},
// iOS 触屏图标
icons: {
icon: "/favicon.ico",
apple: "/favicon.ico",
},
};
export default function RootLayout({