分享我的 Next.js 项目结构约定
团队规模上来之后,App Router 的目录约定变得越来越重要。分享一份我们用了一年的结构: 几个硬约定: app/ 下的 page 不写业务逻辑,只组装。 数据访问统一走 lib/db/ .server.ts ,文件名后缀卡边界。 Server Actions 放 featu
Posts
Start discussions like a forum — great for questions, opinions, tool recommendations, and experience sharing.
团队规模上来之后,App Router 的目录约定变得越来越重要。分享一份我们用了一年的结构: 几个硬约定: app/ 下的 page 不写业务逻辑,只组装。 数据访问统一走 lib/db/ .server.ts ,文件名后缀卡边界。 Server Actions 放 featu
middleware 里要解析登录态,每次都查一次数据库,P95 拖到 80ms。想着迁到 Edge Runtime 上跑会快点,但又怕很多 Node 依赖用不了。 测了下,Edge 上不能直接用 Prisma,得换成 serverless driver 或者干脆只验 JWT。最
不黑不踩,Next.js 文档整体质量不错,但 caching 那一章真的离谱。不同版本默认值变了三回,文档上写的还是老默认值,新人看了直接踩坑。 最让人崩溃的是 "默认 fetch 会缓存" 这条。Next 14 是默认缓存,14.2 之后某些场景又改成不缓存,到 15 默认全
新项目立项,团队在纠结这个。我倾向 Next.js(SSR/SEO 友好),但同事觉得 Vite + React 更灵活、构建快、心智负担小。 我的判断标准大概是这样: 重 SEO、内容型、有 SSR 需求 → Next.js。 中后台、登录后应用、纯交互 → Vite SPA。
几台机器上跑了好几个 Next.js 应用,每个都自带一份 node modules,磁盘和构建时间都顶不住。想试试 shared node modules,但又怕依赖版本冲突。 查了下, output: 'standalone' 模式只会打包运行时真正用到的依赖,体积小很多,但
用 output: 'standalone' 出来的 .next/standalone 目录,理论上拷到服务器直接 node server.js 就能跑。但实际部署我踩了好几个坑。 public/ 和 .next/static 不会被打进 standalone,得手动拷。 路径都
升级到 React 19 后试了下 use() 这个新 hook,能直接读 Promise,写起来确实比 useEffect + useState 简洁。 但用着用着发现几个问题:同一个 Promise 重复 use 不会复用结果,得自己 memo;错误处理还是要靠 ErrorB
升级 React 19 后,发现部分 useEffect 莫名其妙跑了两次。一开始以为是 Strict Mode(本来就跑两次),但 prod 构建里也出现了。 最后定位到是用了 React Compiler 之后,有些 effect 被自动 memo 化,依赖收集变了,触发了额
React 19 的 useFormStatus 配合 Server Actions,做表单提交体验非常好。提交按钮的 loading 态一行就搞定: 关键是不用再手动维护 state,组件也更干净。配合 useActionState 拿错误信息,整个表单几乎零样板代码。 唯一不
试了下 useActionState ,整体思路很好,但 API 设计有点绕。它要传一个 reducer 风格的函数,返回值是 [state, action, isPending] ,跟传统 hook 习惯不太一样。 pending 是后加的,之前还得自己包一个 transiti
React Compiler 上 stable 之后,我把项目里所有的 useMemo 、 useCallback 、 React.memo 全删了,编译器自动处理 memoization。代码瞬间清爽了一大截。 实测性能:大部分场景持平或略好,个别列表渲染场景还快了点。但有一个
satisfies 出来一年多了,团队里用的人不多。我自己用得挺爽,尤其在定义配置对象时,既能保证类型安全,又能保留字面量类型。 跟 as 比最大的区别是: satisfies 是 "校验" 而不是 "断言",类型不符会报错而不是硬转。这点对配置文件、路由表、常量映射特别有用。