技术栈
- 状态管理:zustand 做全局状态管理,要做状态持久化与“恢复”,使用 persist 中间件,将必要 UI 状态保存在本地
- 基础组件 shadcn ui
- pwa 还需要处理 Service Worker。用 @serwist/next ,参考 https://serwist.pages.dev/docs/next/getting-started https://serwist.pages.dev/docs/next/turbo
按需使用:
- 轮播图:Embla Carousel
- 灯箱:Lightbox(灯箱)库 —— Yet Another React Lightbox (YARL)
状态与导航
模态框的开关、应用功能的选择等跟路由高度相关的“状态”,,要充分利用软导航机制,遵从 Modals as Routes交给 URL 来控制。而其他真正的 “全局状态”,使用 zustand。
要主动采用以 URL 为驱动的平行/拦截路由”。既保留 SPA 的流畅感(Client-side Transition),又利用 Next.js 的服务端能力。
不同场景下的导航实现方式参考:
| 需求场景 | 推荐方案 | 理由 |
|---|---|---|
| 全应用级导航 | next/link + Layout | 利用内置的预渲染和代码分割,体验接近 SPA 但性能更优。 |
| 弹窗/抽屉/详情覆盖 | Parallel + Intercepting Routes | 解决“刷新即丢失状态”的痛点,同时保持 URL 同步。 |
| 实时筛选/仪表盘控制 | URL Params (Shallow Updates),用 nuqs 这个库 | 保证交互的即时性,同时允许用户分享当前状态的链接。 |
| 极高频的局部 UI 切换 | React State (Client Component) | 避免任何网络开销,纯内存操作。 |
注意:
- 不要尝试在 App Router 中安装 react-router-dom。这会破坏 Next.js 的缓存机制(Router Cache)和服务器组件(RSC)的优势。
- 善用 useTransition:在进行路由跳转或 Server Action 时,包裹在 startTransition 中,可以避免 UI 冻结,并允许用户在加载期间继续交互。
- Parallel Routes 是需要 default.tsx 的
- Layout 隔离:如果你希望导航时某个侧边栏不重新渲染,请确保它放在 layout.tsx 而非 page.tsx 中。
国际化
用 next-intl 做国际化,效果:
- URL 驱动,不进行自动重定向,由用户自主选择,页面 header 要有Language Switcher,
- 要做软提醒:如果通过 JavaScript 的 navigator.language 检测到用户语言与当前页面不符,在顶部弹出一个小横幅(Banner),询问用户是否切换,如果用户关掉横幅,则继续停留,不再干扰。
- 一旦用户选定了语言,要能在客户端持久化记忆语言偏好,客户端自动跳转到对应语言页面。
- 要有静态SEO优化,在 HTML 头部设置
<link rel="alternate" hreflang="x" href="...">,告诉搜索引擎你支持多语言。 - manifest 也要国际化
- 需要考虑的,既然用了 next-intl , useRouter , useParams 等,需要从 i18n/routing 下面引入。另外,一些特殊的 url 需要排除,比如 api 、 serwist/sw.js 等
