
Vercel 八月初发了 Next.js 16.3 正式版,并补了一篇 v0 的实战复盘:Instant Navigations。你点链接后,页面要不要先“愣一下”,现在被拆成了明确的路由契约,而不只是“多加几个 skeleton”。
昨天写过 Turbopack 和 dev 内存。今天换一条线:导航手感。两者都在 16.3,但解决的痛不一样——一个是本地会话能不能扛住,一个是用户点完能不能立刻有反馈。
问题其实很土
App Router + RSC 的默认故事是:点 Link → 等服务器 → 再换页。数据新、HTML 真,但手指觉得慢。SPA 反过来:客户端先切壳,数据后到,手感好,却容易把“服务端真相”弄糊。
Instant Navigations 的野心是两边都要:服务器仍主导渲染,点击反馈尽量像客户端路由。它不是一个魔术开关,而是逼你给每条路由回答同一个问题——用户点完立刻看到什么?
三条出路:stream / cache / block
官方把即时性收敛成几类行为(需配合 cacheComponents 等 opt-in):
- Stream:立刻推一个带 Suspense 的壳,慢数据自己补位。
- Cache:
'use cache'等路径上直接端出已缓存 UI,导航近乎本地。 - Block / 明确退出:
export const instant = false(或等价退出),承认这条路就是要等,别假装闪。
我喜欢这种粗鲁的诚实。以前慢导航常被 loading.tsx 和乐观 UI 东补西补;现在框架把“是否即时”抬成可测试、可回归的属性。
v0 的案例更直白:他们先用洞察工具揪出“点了也不像即时”的路由,再逐条修。公开图表里,从点击到路由切换大约快了 3.5 倍量级——具体数字随产品变,方向清楚:先度量,再改契约,而不是先上全局动画骗眼睛。
instant():给人和 Agent 用的验收钩
16.3 里比较新的一点是 instant() 测试辅助。它让你(或 coding agent)写失败测试:这条导航必须被判定为 instant,否则红。
结合他们提到的 optimizer skill,流程可以很工程化:
// 示意:用 instant() 锁住“点击后应立即切换”的路由
import { instant } from 'next/experimental/testing' // 以你安装的 16.3 文档为准
it('settings → billing feels instant', async () => {
await instant('/settings/billing')
})
别把版本 API 背死,去看你锁文件对应的文档。重要的是产品姿态:导航手感进 CI,而不是只活在设计走查里。Agent 改路由时,有红灯可比“感觉好像快点了”可靠得多。
落地时我会先做的四件事
1. 列导航热路径,而不是全站一刀切
首页 → 项目、列表 → 详情、设置里的高频页。先给这些路由定 stream / cache / 退出策略。冷门管理页慢一点,用户多半能忍;核心回路卡一下,会记很久。
2. 壳和数据边界画清楚
Stream 的壳必须轻:布局、导航、关键操作入口。别把半页业务查询塞进“即时壳”,否则 Suspense 只是把白屏改成转圈。
3. Cache 要有失效故事
缓存 UI 让导航飞,也会让“刚改完怎么还是旧的”变成客服工单。写清 tag / revalidate 与谁在写数据。没有失效设计的 instant,是技术债加速器。
4. 和 React Compiler、Turbopack 分开评估
Compiler 砍的是客户端重渲染账单;Turbopack 砍的是 dev/build 体感;Instant Navigations 砍的是点到切换。可以同一周都碰,但指标别混:CLS/INP、RSS、TTR(time-to-route)各记各的。
图:明亮工作台上的浏览器多标签与路由草图(与封面不同机位)

和“假 SPA”划界
有团队一听 instant,就想回到全家桶客户端路由。我会反着来:
- 鉴权墙、支付结果、权限敏感页:宁可 block 或短 stream,也不要先闪无权限再踢出去。
- 营销落地页:cache 友好,注意预览/草稿别进同一缓存键。
- 强个性化首页:stream 壳 + 分区缓存,比整页
'use cache'安全。
Instant 是体验目标,不是道德正确。该等的等,且让等待可解释。
小结
Next.js 16.3 的 Instant Navigations 把“点了之后立刻有什么”收成路由级契约,并用 instant() 一类工具推进可回归。v0 的复盘说明:这事适合度量驱动,也适合交给 agent 扫慢路由,但不适合无脑全局开启。
若你这周只做一件事:挑三条最热导航,写下各自的 stream / cache / block 决策,再补一条自动化检查。手感往往不是从“再优化一点 fetch”来的,而是从“我们是否承认这条路做不到即时”开始的。


