之前的文章中已经多次提到了路由段配置项,路由段配置选项可以配置页面、布局、路由处理程序的行为,本篇我们会详细介绍其中的配置内容。
如果大家翻阅 Next.js 的官方文档(英文),会经常发现 Segment 这个单词,其释义为:
为了简单起见,我翻译成“段”。Segment 放到 URL 这个场景时:
URL Segment 指的是由斜杠分隔的 URL Path 的一部分 URL Path 指的则是域名后面的 URL 部分(URL Path 由 URL Segment 组成)
用这张图表示更清晰一些:
Segment 放到 Route 这个场景时:
Router Segment,我翻译为“路由段”,路由中的每个文件夹都代表一个路由段。每个路由段都映射一个对应的 URL Segment:
在这张图中,/dashboard/settings
由三段组成:
/
:根段(Root Segment)dashboard
:段(Segment)settings
:叶段(Leaf Segment)PS:叶段指的是没有子节点的段。
接下来我们来到本章的正题——路由段配置。
路由段配置选项可以配置页面、布局、路由处理程序的行为。比如我们使用 fetch 的时候可以单独配置某个请求的 revalidate
,借助路由段配置,我们可以配置这个路由下所有 fetch 请求的 revalidate
。
路由段配置的使用方式也很简单,导出一个约定变量名即可,比如:
// layout.js | page.js | route.js
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
export const maxDuration = 5
export default function MyComponent() {}
具体这些变量名和值的类型为:
变量名 | 类型 | 默认值 |
---|---|---|
dynamic | 'auto' | 'force-dynamic' | 'error' | 'force-static' |
'auto' |
dynamicParams | boolean |
true |
revalidate | false | 'force-cache' | 0 | number |
false |
fetchCache | 'auto' | 'default-cache' | 'only-cache' | 'force-cache' | 'force-no-store' | 'default-no-store' | 'only-no-store' |
'auto' |
runtime | 'nodejs' | 'edge' |
'nodejs' |
preferredRegion | 'auto' | 'global' | 'home' | string | string[] |
'auto' |
maxDuration | number |
部署平台设置 |
注意配置选项的值目前是静态分析的,也就是说,配置revalidate = 600
是有效的,但是 revalidate = 60 * 10
是无效的。
我们来一一讲解这些配置选项的作用。
更改布局或者页面的动态行为,用例如下:
// layout.js | page.js | route.js
export const dynamic = 'auto'
// 'auto' | 'force-dynamic' | 'error' | 'force-static'
为了讲解 dynamic 参数的选项,我们先复习下基础知识:
所谓静态渲染(Static Rendering),指的是路由在构建时渲染,或者在重新验证后后台渲染,其结果会被缓存并可以推送到 CDN。适用于未针对用户个性化且数据已知的情况,比如静态博客文章、产品介绍页面等。
所谓动态渲染(Dynamic Rendering),指的是路由在请求时渲染,适用于针对用户个性化或依赖请求中的信息(如 cookie、URL 参数)的情况。
因为渲染模式和数据缓存是相互独立的,所以在动态渲染下,数据请求也分为缓存和不缓存(uncached data request)的。默认是缓存,这样做的好处在于,即便选择了动态渲染,也不用担心渲染时获取所有数据对性能造成影响。
dynamic
影响的不仅是渲染模式,也会影响数据缓存的方式。
还有一个名词叫动态函数(Dynamic Functions),指的是获取只能在请求时才能得到的信息(如 cookie、请求头、URL 参数)的函数,在 Next.js 中,对应的就是 cookies()
、headers()
、useSearchParams()
、searchParams()
这些函数。如果使用了这些函数的任意一个,都会导致路由进行动态渲染。
接下来我们讲解 dynamic
的值都有哪些作用:
'auto'
(默认):自动判断'force-dynamic'
,强制动态渲染和退出所有 fetch 请求缓存,相当于:
getServerSideProps()
fetch()
请求都设置为 { cache: 'no-store', next: { revalidate: 0 } }
export const fetchCache = 'force-no-store'
'error'
强制静态渲染并缓存数据,如果有组件使用了动态函数或不缓存数据请求(uncached data request),就会导致错误,相当于:
getStaticProps()
fetch()
请求都设置为 { cache: 'force-cache' }
fetchCache = 'only-cache', dynamicParams = false
dynamic = 'error'
会更改 dynamicParams
的默认值 true
为 false
'force-static'
强制静态渲染并缓存数据,强制 cookies()
、headers()
、useSearchParams()
返回空值。控制当访问不是由 generateStaticParams
生成的动态路由段的时候发生什么。
// layout.jsx | page.jsx
export const dynamicParams = true // true | false,
true
(默认):按需生成这个选项对应 Page Router 下的 getStaticPaths
的 fallback: true | false | blocking
选项。
如果使用了 dynamic = 'error'
和 dynamic = 'force-static'
,它会更改 dynamicParams
的默认值为 false
。
设置布局或者页面的默认验证时间。此设置不会覆盖单个 fetch
请求设置的 revalidate
的值。注意 revalidate
选项只能用于 Nodejs Runtime,不能用于 Edge Runtime。
// layout.jsx | page.jsx | route.js
export const revalidate = false
// false | 'force-cache' | 0 | number
false
(默认),语义上相当于 revalidate: Infinity
,资源无限期缓存。0
,页面或布局总是动态渲染,即使没有使用动态函数或者不缓存数据请求(uncached data request)。number
:设置布局或页面的默认重新验证频率,以秒为单位。关于重新验证频率,一个路由可能有多个布局和一个页面,此时会选择最低的 revalidate
值作为路由的重新验证频率。这是为了确保子路由的重新验证时间频率和父布局保持一致。此外,单个 fetch 请求可以设置比路由默认的 revalidate
值更低的 revalidate
值,这会增加整个路由的重新验证频率。这允许你根据某些动态条件进行更频繁的重新验证。
这是一个高级选项,仅当你特别需要覆盖默认行为时才应该使用。为了解释这个选项,我们先复习下 fetch 请求的 options.cache
选项:
fetch(`https://...`, { cache: 'force-cache' | 'no-store' })
其中 force-cache
是默认值,表示优先从缓存中查找匹配请求,当没有匹配项或者匹配项过时时,才从服务器上获取资源并更新缓存。no-store
表示每次请求都从服务器上获取资源,不从缓存中查,也不更新缓存。
回到 Next.js,默认情况下,Next.js 会缓存在动态函数使用之前的 fetch
请求,不会缓存任何动态函数之后的fetch
请求。而 fetchCache
允许你覆盖布局或者页面中所有的 fetch
请求的默认 cache
选项。
// layout.jsx | page.jsx | route.js
export const fetchCache = 'auto'
// 'auto' | 'default-cache' | 'only-cache'
// 'force-cache' | 'force-no-store' | 'default-no-store' | 'only-no-store'
'auto'
(默认):动态函数之前按照开发者设置的 cache
选项进行缓存,动态函数之后不缓存请求'default-cache'
:开发者可以自由设置 cache
选项,但如果开发者未设置 cache
选项,默认设置为 force-cache
,这意味着即使是在动态函数之后的请求,也会被视为静态'only-cache'
:如果开发者未设置 cache
选项,默认设置为 force-cache
,如果有请求设置成 cache: 'no-store'
,则会导致报错'force-cache'
:将所有请求的 cache
选项设置为 force-cache
。'default-no-store'
:开发者可以自由设置 cache
选项,但如果开发者未设置 cache
选项,默认设置为 no-store
,这意味着即使是在动态函数之前的请求,也会被视为动态。'only-no-store'
:如果开发者未设置 cache
选项,默认设置为 no-store
,如果有请求设置成 cache: 'force-cache'
,则会导致报错'force-no-store'
:将所有请求的 cache
选项设置为 no-store
。一个路由可能有多个布局和一个页面,此时选项应该相互兼容:
'only-cache'
和 'force-cache'
同时提供,'force-cache'
获胜。如果 'only-no-store'
和 'force-no-store'
同时提供,'force-no-store'
获胜。带 force
的选项会更改整个路由的行为,并会阻止 'only-*'
引发的错误。'only-*'
和 force-*'
选项的作用就是确保整个路由要么是完全静态要么是完全动态,这意味着:
'only-cache'
和 'only-no-store'
'force-cache'
和 'force-no-store'
'auto'
或 '*-cache'
,父级无法使用 'default-no-store'
,因为这会导致请求有不同的行为。Next.js 建议共享的父布局使用 'auto'
,在子级中自定义不同的选项。
设置运行时环境,具体参考小册《渲染篇 | Streaming 和 Edge Runtime》
// layout.jsx | page.jsx | route.js
export const runtime = 'nodejs'
// 'edge' | 'nodejs'
nodejs
(默认)edge
在 Vercel Serverless Functions 中使用,搭配 export const runtime = 'edge';
,用于设置 Edge Functions 执行的区域,默认情况下,Edge Functions 在最接近传入请求的区域中执行,但如果你的函数比较依赖数据源,你会更希望它靠近数据源所在的位置以实现快速响应,那就可以设置 preferredRegion 指定一系列首选区域。
指定区域的时候,传入的是区域 ID,区域列表参考 Vercel 的 Region List 文档,其中 iad1 表示美国东部区域,参考位置美国华盛顿地区,sfo1 表示美国西部,参考位置美国旧金山。
// layout.jsx | page.jsx | route.js
export const preferredRegion = 'auto'
// 'auto' | 'global' | 'home' | ['iad1', 'sfo1']
在 Vercel Serverless Functions 中使用,用于配置 Vercel 函数的最大持续时间,所谓 Max duration,指的是函数在响应之前可以处理 HTTP 请求的最长时间。如果持续时间内没有响应,则会返回错误码。如果没有指定,根据不同的部署平台,默认时间会不同。
export const maxDuration = 5
与动态路由搭配使用,用于定义静态生成的路由段参数。具体内容参考小册《API 篇 | 路由相关的常用方法》