PAYATHON 2026

Next.js 客户端路由切换时如何更新 Permissions Policy?

数据小陈

结论

通过 Next.js <Link> 进行客户端导航时,浏览器不会加载新的 HTML 文档。即使 middleware.ts 为页面 B 的内部数据请求返回了新的 Permissions-Policy 响应头,当前文档采用的策略也不会随之改变。要让页面 B 使用另一套策略,需要触发完整的文档导航;如果继续使用客户端导航,同一个 SPA 文档就应采用一致的 Permissions Policy。

为什么页面仍在使用策略 X

题目描述的过程是:页面 A 返回策略 X。点击 <Link> 后,Next.js 请求页面 B 的 JSON props 数据,响应中包含策略 Y。页面 B 的界面更新了,但浏览器仍按策略 X 运行。完整刷新页面 B 后,浏览器才采用策略 Y。

这是因为客户端路由请求只用于获取页面数据并更新当前文档,不会触发新的顶层文档导航。浏览器在加载页面文档时,才会根据响应头设置该文档的 Permissions Policy。数据请求中返回的同名响应头不会把当前文档的策略从 X 改为 Y。

可选处理方式

让页面使用同一套策略

如果多个页面可以共用一套权限策略,可以在中间件中按需生成响应头,并确保这套策略适用于通过客户端路由访问的页面。例如:

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const response = NextResponse.next()
  const policy = 'camera=(), microphone=()' // 替换为应用需要的策略

  response.headers.set('Permissions-Policy', policy)
  return response
}

这段代码可以设置文档响应的策略,但 <Link> 发起的客户端导航不会因此替换当前文档的策略。示例中的策略仅用于展示响应头的设置方式,应按应用的实际需要配置。

需要不同策略时触发完整页面加载

如果页面 B 必须使用不同于页面 A 的策略,就让导航加载新的文档。可以使用普通链接,也可以显式执行完整导航:

window.location.assign('/page-b')

完整加载时,浏览器会收到页面 B 的文档响应,并采用其中的 Permissions-Policy。这种方式会触发完整页面加载,是否适合要看应用对导航体验的要求。

注意事项

不要根据页面 B 的 JSON props 响应头是否包含策略 Y,来判断浏览器是否已更新当前文档的策略。应检查页面 B 的文档导航响应,并结合浏览器的实际执行结果确认策略。

如果既要保留客户端导航,又要让不同页面使用不同的文档级 Permissions Policy,这与当前文档的导航机制不相符。此时需要统一文档策略,或在页面边界处改用完整导航。

备注:内容仅供参考。