From 4083cf0b6c1858e8cecb7d8da9d622d2827d4185 Mon Sep 17 00:00:00 2001 From: chenhang Date: Mon, 13 Jul 2026 18:45:59 +0800 Subject: [PATCH] refactor: remove obsolete config and cross-layer exports Drop the temporary static-generation retry override and stale hydration suppression. Refresh outdated Next.js and migration comments, and stop re-exporting Result through the storage layer. --- next.config.ts | 73 ++++--------------- src/app/global-error.tsx | 8 +- src/app/layout.tsx | 14 +--- src/app/page.tsx | 8 +- .../interceptor/auth_refresh_interceptor.ts | 4 +- .../net/interceptor/logging_interceptor.ts | 4 +- src/core/net/interceptor/token_interceptor.ts | 4 +- .../interfaces/ichat_repository.ts | 7 +- src/data/storage/chat/local_chat_storage.ts | 2 +- src/data/storage/index.ts | 10 +-- src/utils/result.ts | 15 +--- 11 files changed, 31 insertions(+), 118 deletions(-) diff --git a/next.config.ts b/next.config.ts index b427f648..1ce03977 100644 --- a/next.config.ts +++ b/next.config.ts @@ -2,21 +2,9 @@ import { withSentryConfig } from "@sentry/nextjs"; import type { NextConfig } from "next"; import { withSerwist } from "@serwist/turbopack"; -/** - * Next.js 16 临时绕过 `/_global-error` prerender 的 workStore bug - * 标记根 layout 不参与静态预渲染(global-error 会在请求时渲染) - * https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config - * - * 容器化部署模型:`output: "standalone"` + Docker Compose。 - * - `pnpm build` 产出 .next/standalone、.next/static、public。 - * - Dockerfile 运行 `node server.js`,仅复制 standalone traced runtime 依赖。 - */ const nextConfig: NextConfig = { + // Docker runs the traced runtime emitted to `.next/standalone`. output: "standalone", - experimental: { - // 关闭静态优化以规避 16.2.7 global-error prerender bug - staticGenerationRetryCount: 0, - }, images: { remotePatterns: [ { @@ -44,48 +32,19 @@ const shouldUploadSentrySourcemaps = process.env.CI !== "true" || process.env.SENTRY_UPLOAD_SOURCEMAPS === "1"; export default withSentryConfig(withSerwist(nextConfig), { - // For all available options, see: - // https://www.npmjs.com/package/@sentry/webpack-plugin#options - - org: "shenzhen-banlv-zhidao-technolo", - - project: "javascript-nextjs", - - // Only print logs for uploading source maps in CI - silent: !process.env.CI, - - // Keep build metadata local; application errors/performance are configured separately. - telemetry: false, - - // For all available options, see: - // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ - - // Upload a larger set of source maps for prettier stack traces (increases build time) - widenClientFileUpload: true, - - // PR/branch CI should validate builds without uploading source maps. Release jobs can - // set SENTRY_UPLOAD_SOURCEMAPS=1 to enable uploads explicitly. - sourcemaps: { - disable: !shouldUploadSentrySourcemaps, - }, - - // Uncomment to route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers. - // This can increase your server load as well as your hosting bill. - // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client- - // side errors will fail. - // tunnelRoute: "/monitoring", - - webpack: { - // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.) - // See the following for more information: - // https://docs.sentry.io/product/crons/ - // https://vercel.com/docs/cron-jobs - automaticVercelMonitors: true, - - // Tree-shaking options for reducing bundle size - treeshake: { - // Automatically tree-shake Sentry logger statements to reduce bundle size - removeDebugLogging: true, - }, - }, + org: "shenzhen-banlv-zhidao-technolo", + project: "javascript-nextjs", + silent: !process.env.CI, + telemetry: false, + widenClientFileUpload: true, + // Validation builds keep source maps local; release jobs opt in to upload. + sourcemaps: { + disable: !shouldUploadSentrySourcemaps, + }, + webpack: { + automaticVercelMonitors: true, + treeshake: { + removeDebugLogging: true, + }, + }, }); diff --git a/src/app/global-error.tsx b/src/app/global-error.tsx index 16589d02..622473e6 100644 --- a/src/app/global-error.tsx +++ b/src/app/global-error.tsx @@ -3,12 +3,8 @@ /** * 全局 Error Boundary * - * Next.js 16 文档要求 global-error 必须是 Client Component。 - * 16.2.7 存在 prerender `/_global-error` 的内部 bug(workStore 未初始化), - * 本文件通过不挂任何 Client Context 副作用、纯静态 HTML 输出来规避。 - * - * 当根 layout 自身抛出错误时渲染;必须包含 `` + ``, - * 因为它会替换根 layout。 + * global-error 必须是 Client Component,并自行提供 `` 和 ``, + * 因为它会在根 layout 渲染失败时替换整个文档。 */ import { ExceptionHandler } from "@/core/errors"; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 77c28045..2d063394 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -9,7 +9,7 @@ import { RootProviders } from "@/providers/root-providers"; export const metadata: Metadata = { title: "cozsweet", description: "cozsweet frontend (Next.js)", - // PWA:链接到 public/manifest.json(由 @ducanh2912/next-pwa 体系使用) + // Static web app manifest served from `public/`. manifest: "/manifest.json", // iOS Safari "添加到主屏" 元数据 appleWebApp: { @@ -24,17 +24,11 @@ export const metadata: Metadata = { }, }; -/** - * Next.js 14+ 推荐:viewport 相关元数据独立导出。 - * 之前放在 `metadata.themeColor` 会在 Next.js 16 触发 deprecation 警告。 - * 详见 https://nextjs.org/docs/app/api-reference/functions/generate-viewport - */ export const viewport: Viewport = { // 浏览器顶栏 / Android PWA 顶栏颜色 themeColor: "#f84d96", // 让页面延伸到 notch / home indicator 区域, // env(safe-area-inset-bottom) 才能取到非零值(见 chat-input-bar.module.css)。 - // Next.js 16 的 Viewport 类型未列出此键,但 generate-viewport.md 允许附加原始 meta 值。 viewportFit: "cover", }; @@ -44,19 +38,15 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - // suppressHydrationWarning:next/font + Tailwind v4 偶发类名差异;详见 - // `src/app/api/auth/[...nextauth]/route.ts` 的"水合闪屏"说明。 {/* NextAuth SessionProvider:为所有客户端组件提供 useSession() 上下文 */} - {/* PWA Service Worker 注册器 —— Serwist Turbopack 在 build 时编译 app/sw.ts, - 通过 /serwist/sw.js 路由 handler 服务。SerwistProvider 内部处理注册 + 生命周期。 */} + {/* SerwistProvider registers the service worker built from app/sw.ts. */} {children} diff --git a/src/app/page.tsx b/src/app/page.tsx index 3b935c5e..f16d6bbc 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,12 +1,8 @@ /** * 根路径处理 * - * Server Component:把访客直接送入 `/splash`,由 splash 页(Client)根据 - * `authStorage.hasLoginToken()` 决定是否再跳 `/chat`。 - * - * 这里不做鉴权重定向:Server 端读不到 localStorage,且当前没有 HttpOnly - * cookie(见 `src/data/storage/auth/auth_storage.ts` 的 TODO)。 - * `src/proxy.ts` 已为未来 cookie 化预留了基于 `login_token` cookie 的 short-circuit。 + * 根页面只负责进入 splash。浏览器端认证初始化完成后,再由导航守卫决定 + * 进入聊天页或保留在启动页。 */ import { redirect } from "next/navigation"; diff --git a/src/core/net/interceptor/auth_refresh_interceptor.ts b/src/core/net/interceptor/auth_refresh_interceptor.ts index 1a70dad8..a52ed755 100644 --- a/src/core/net/interceptor/auth_refresh_interceptor.ts +++ b/src/core/net/interceptor/auth_refresh_interceptor.ts @@ -229,9 +229,7 @@ export const onResponseErrorAuthRefresh: FetchHook = async (ctx) => { } }; -/** - * 兼容旧接口的 FetchHooks 形式 - */ +/** Hooks consumed by the shared ofetch client. */ export const authRefreshInterceptor = { onResponseError: onResponseErrorAuthRefresh, }; diff --git a/src/core/net/interceptor/logging_interceptor.ts b/src/core/net/interceptor/logging_interceptor.ts index 0051db95..bfb9bd08 100644 --- a/src/core/net/interceptor/logging_interceptor.ts +++ b/src/core/net/interceptor/logging_interceptor.ts @@ -50,9 +50,7 @@ export const onErrorLogging: FetchHook = async (ctx) => { ); }; -/** - * 兼容旧接口的 FetchHooks 形式(保留以备兼容) - */ +/** Hooks consumed by the shared ofetch client. */ export const loggingInterceptor = { onRequest: onRequestLogging, onResponse: onResponseLogging, diff --git a/src/core/net/interceptor/token_interceptor.ts b/src/core/net/interceptor/token_interceptor.ts index 5aa75b59..08ec4339 100644 --- a/src/core/net/interceptor/token_interceptor.ts +++ b/src/core/net/interceptor/token_interceptor.ts @@ -104,9 +104,7 @@ export const onRequestToken: FetchHook = async (ctx) => { } }; -/** - * 兼容旧接口的 FetchHooks 形式 - */ +/** Hooks consumed by the shared ofetch client. */ export const tokenInterceptor = { onRequest: onRequestToken, }; diff --git a/src/data/repositories/interfaces/ichat_repository.ts b/src/data/repositories/interfaces/ichat_repository.ts index 92636a3d..ad6bda3a 100644 --- a/src/data/repositories/interfaces/ichat_repository.ts +++ b/src/data/repositories/interfaces/ichat_repository.ts @@ -3,12 +3,7 @@ /** * IChatRepository 接口 * - * 对齐 Dart 端 `ChatRepository` 抽象(lib/data/repositories/chat_repository.dart): - * - 远程:发送消息、获取历史 - * - 本地:写入 / 批量覆盖 / 读取 / 清空 / 计数 - * - * 私有助手(`_chatToLocal` / `_localToChat` / `_mapLocalStorageResult`)不暴露。 - * + * 聚合聊天远程操作、身份隔离的本地历史,以及媒体缓存能力。 */ import type { Result } from "@/utils"; diff --git a/src/data/storage/chat/local_chat_storage.ts b/src/data/storage/chat/local_chat_storage.ts index 3da46dfe..98c5d018 100644 --- a/src/data/storage/chat/local_chat_storage.ts +++ b/src/data/storage/chat/local_chat_storage.ts @@ -1,7 +1,7 @@ "use client"; /** - * LocalChatStorage 完整实现(示范 2:IndexedDB via Dexie) + * IndexedDB-backed chat message storage. * * Dexie 实例可注入,便于测试用 fake-indexeddb 跑真 Dexie。 * diff --git a/src/data/storage/index.ts b/src/data/storage/index.ts index d669a7b7..9f7176f1 100644 --- a/src/data/storage/index.ts +++ b/src/data/storage/index.ts @@ -1,17 +1,9 @@ /** - * @file Storage 公共导出 - * - * unstorage 重构后: - * - 删除 `./local_storage`(原自定义 LocalStorage class 已被 unstorage 取代) - * - 业务层(AuthStorage / ChatStorage / UserStorage / AppStorage)继续走原接口 + * @file Storage public exports. */ -export * from "@/utils/result"; export * from "./storage_keys"; export * from "./storage_migration"; export * from "./app/app_storage"; -// NOTE: top-level `auth_storage.ts` is intentionally not re-exported here — -// it conflicts with `auth/auth_storage.ts` (both define `AuthStorage`). -// Import directly via `@/data/storage/auth/auth_storage` instead. export * from "./auth/auth_storage"; export * from "./auth/iauth_storage"; export * from "./chat/chat_storage"; diff --git a/src/utils/result.ts b/src/utils/result.ts index 95967c49..af9b0b33 100644 --- a/src/utils/result.ts +++ b/src/utils/result.ts @@ -1,16 +1,7 @@ /** - * 仓库层统一 Result + * 仓库和持久化操作共享的 Result。 * - * 与 `src/data/storage/result.ts` 的 `Result`(`{kind, value}` 形态)并存: - * - 本类型供仓库层(`src/data/repositories/*`)使用,`{success, data}` 形态更贴近 - * 原 Dart `Result.success` / `Result.failure` 命名与 API 端 envelope 风格。 - * - 存储层继续使用 `{kind, value}`,因为它的消费者(localStorage、Dexie)已经在 - * 大量代码中 pattern-match `r.kind`。 - * - 两个类型路径不同(`@/data/result` vs `@/data/storage/result`),不冲突; - * 如需在同模块中混用,可用 `import { Result as StorageResult } from - * "@/data/storage/result"` 别名。 - * - * `error` 仍固定为 `Error`(非 `unknown`):仓库 `Result.wrap` 捕获后用 + * `error` 固定为 `Error`(非 `unknown`):`Result.wrap` 捕获后用 * `ExceptionHandler` 统一归一化为 `AppException`,调用方可以稳定读取 * `error.message`;需要结构化错误时可继续通过 `ExceptionHandler.handle(error)` * 得到简化后的 `{ code, message }`。 @@ -23,7 +14,7 @@ export type Result = | { readonly success: true; readonly data: T } | { readonly success: false; readonly error: Error }; -/** 仓库层 Result.wrap 专用 logger —— 自动带 component: "Result" 标签 */ +/** Result.wrap 专用 logger —— 自动带 component: "Result" 标签 */ const log = new Logger("Result"); export const Result = {