cdn-caching

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Vercel Caching

Vercel 缓存

You are an expert in understanding Vercel's caching infrastructure, and how the CDN Cache, ISR, and PPR work.
你是理解Vercel缓存基础设施以及CDN缓存、ISR和PPR工作原理的专家。

Core Knowledge

核心知识

  • ISR (and PPR, a rendering strategy built on it) is a framework feature — Next.js, SvelteKit, Nuxt, and Astro all use it on Vercel, and the layers, metrics, and CLI here apply regardless. (For caching data between your function and a backend, that's the Runtime Cache — a separate layer; see References.)
  • PPR (Partial Prerendering) — a rendering strategy, not a cache layer: the static shell lives in the ISR cache while a function renders the dynamic holes per request and streams them into the same response. A route with holes still invokes the function on a shell hit; a holeless route is just ISR (a pure
    prerender
    HIT).
  • ISR(以及基于它构建的渲染策略PPR)是一种框架特性——Next.js、SvelteKit、Nuxt和Astro在Vercel上均支持该特性,本文涉及的层级、指标和CLI工具均通用。(若要在函数与后端之间缓存数据,需使用Runtime Cache——这是一个独立的缓存层级;详见参考资料。)
  • PPR(Partial Prerendering,部分预渲染)——是一种渲染策略,而非缓存层级:静态外壳存储在ISR缓存中,同时函数会针对每个请求渲染动态部分并将其流式传输到同一响应中。包含动态部分的路由在命中静态外壳时仍会调用函数;无动态部分的路由则完全等同于ISR(纯
    prerender
    命中)。

How caching works

缓存工作原理

Vercel caches at multiple layers between the visitor and your backend. A request reaches the nearest PoP, which routes to a Vercel region; the CDN then checks each layer in order and returns a cached response as soon as one is available, so your function runs only when nothing upstream has a valid copy.
Vercel在访问者与后端之间设置了多层缓存机制。请求会先到达最近的PoP(边缘节点),再路由到Vercel区域;随后CDN会按顺序检查每个层级,一旦找到可用的缓存响应就立即返回,因此只有当上游所有缓存都没有有效副本时,才会运行你的函数。

Cache layers

缓存层级

  • CDN cache — regional, ephemeral. On a hit the region returns the response with no function call. Reads/writes are free.
  • ISR cache — durable, in a single Function region. On a CDN miss, Vercel reads here before invoking your function (cache shielding), then replicates the result back to the CDN. Survives deploys for 31 days or until revalidated; reads/writes are billed in 8 KB units.
  • Function invocation — runs only if neither cache has a valid copy. It may read the Runtime/data cache (a separate layer; see References) and your backend, then Vercel stores the response in the ISR cache.
  • Image cache — optimized images, cached on the CDN after the first transform.
  • Purges propagate globally in ~300 ms.
Request collapsing: when many requests hit the same uncached path at once, Vercel collapses them into one function invocation per region to protect the origin.
  • CDN缓存——区域级、临时缓存。命中时,区域节点无需调用函数即可直接返回响应。读写操作免费
  • ISR缓存——持久化缓存,存储在单个函数区域。当CDN缓存未命中时,Vercel会先读取ISR缓存(缓存屏蔽),再将结果同步回CDN缓存。该缓存可在部署后保留31天,或直到被重新验证;读写操作按8 KB单位计费
  • 函数调用——仅当CDN缓存和ISR缓存均无有效副本时才会触发。函数可能会读取Runtime/数据缓存(独立层级;详见参考资料)和后端数据,随后Vercel会将响应存储到ISR缓存中。
  • 图片缓存——经过优化的图片,首次转换后会被缓存到CDN。
  • 缓存清除操作会在约300毫秒内全局生效。
请求合并:当大量请求同时访问同一未缓存路径时,Vercel会将每个区域的请求合并为一次函数调用,以保护源站。

Key concepts

关键概念

  • Cache hit rate — share served from cache (
    HIT
    /
    STALE
    /
    PRERENDER
    ) versus origin (
    MISS
    /
    REVALIDATED
    ). Measure it over cacheable requests — exclude
    BYPASS
    and
    (not set)
    (redirects, errors, uncacheable methods), or they drag the ratio down for non-cache reasons. Low hit rate means more origin load and higher latency.
  • Revalidation — refreshing cached content. Time-based runs automatically after an interval; on-demand runs when you call an API. Both use stale-while-revalidate: visitors keep getting the cached version while the new one regenerates in the background.
  • Invalidate vs. dangerously-delete — two ways to clear content, with very different blast on hit rate:
    • Invalidate (
      invalidateByTag
      , Next.js
      revalidateTag
      /
      revalidatePath
      ) = stale-while-revalidate. Keeps serving stale while refreshing in the background → response shows
      x-vercel-cache: STALE
      .
    • Dangerously-delete (
      dangerouslyDeleteByTag
      , Next.js
      updateTag
      or a revalidate with no lifetime) = hard removal. The next request blocks in the foreground to regenerate →
      x-vercel-cache: REVALIDATED
      .
  • Cache tags & blast radius — tags group cached entries so one call can clear many. A coarse tag attached to thousands of paths has a large blast radius: a single write drops them all and the hit rate collapses until they re-warm. Prefer granular tags (
    product-${id}
    ) plus a roll-up tag.
  • Cache status / cache reason (
    x-vercel-cache
    response header):
    ValueMeaning
    HIT
    Served from cache; no function ran
    MISS
    Not cached; origin/function ran
    STALE
    Served stale while revalidating in background (SWR / invalidate)
    PRERENDER
    Served a prerendered ISR/PPR shell
    REVALIDATED
    Foreground revalidation after a delete (or
    Pragma: no-cache
    )
    BYPASS
    Caching skipped (
    no-store
    ,
    private
    , cookies, etc.)
  • 缓存命中率——从缓存(
    HIT
    /
    STALE
    /
    PRERENDER
    )提供服务的请求占比,与从源站(
    MISS
    /
    REVALIDATED
    )提供服务的请求占比相对。需针对可缓存请求统计该指标——排除
    BYPASS
    (not set)
    (重定向、错误、不可缓存方法),否则这些非缓存原因会拉低命中率。命中率低意味着源站负载更高、延迟更大。
  • 重新验证——刷新缓存内容。基于时间的重新验证会在间隔时间后自动触发;按需重新验证会在调用API时触发。两者均采用stale-while-revalidate策略:访问者在后台生成新版本期间仍会获取缓存版本。
  • 失效(Invalidate)与危险删除(dangerously-delete)——两种清除内容的方式,对命中率的影响截然不同:
    • 失效
      invalidateByTag
      、Next.js的
      revalidateTag
      /
      revalidatePath
      )= stale-while-revalidate策略。在后台刷新期间仍提供过期内容 → 响应头显示
      x-vercel-cache: STALE
    • 危险删除
      dangerouslyDeleteByTag
      、Next.js的
      updateTag
      或无生命周期的重新验证)= 强制删除。下一次请求会在前台阻塞以重新生成内容 →
      x-vercel-cache: REVALIDATED
  • 缓存标签与影响范围——标签用于对缓存条目进行分组,以便一次调用即可清除多个条目。若一个宽泛的标签关联了数千个路径,其影响范围会很大:一次写入操作会清除所有关联条目,命中率会在重新预热前骤降。建议优先使用细粒度标签(如
    product-${id}
    ),再搭配一个汇总标签。
  • 缓存状态/缓存原因
    x-vercel-cache
    响应头):
    取值含义
    HIT
    从缓存返回;未运行函数
    MISS
    未命中缓存;运行了源站/函数
    STALE
    返回过期内容,同时在后台重新验证(SWR/失效操作)
    PRERENDER
    返回预渲染的ISR/PPR静态外壳
    REVALIDATED
    删除后进行前台重新验证(或
    Pragma: no-cache
    BYPASS
    跳过缓存(
    no-store
    private
    、Cookie等原因)

Investigating cache issues

排查缓存问题

Reach for the Vercel CLI.
vercel metrics
gives aggregate numbers (requires Observability Plus);
vercel logs
shows per-request behavior.
Metrics need to be queried by team and project (
-S <team> -p <project>
). Filter production with
-f "environment eq 'production'"
(there is no
--prod
flag). Run
vercel metrics schema <metric>
to discover dimensions; use
-F json
for machine-readable output. With
-g
, remember
--limit
is per time bucket
— omit
-g
when you need totals across the whole window.
使用Vercel CLI工具。
vercel metrics
可提供聚合数据(需Observability Plus);
vercel logs
可查看单请求的行为详情。
指标需按团队和项目查询(
-S <team> -p <project>
)。使用
-f "environment eq 'production'"
过滤生产环境数据(无
--prod
参数)。运行
vercel metrics schema <metric>
可查看指标维度;使用
-F json
可获取机器可读格式的输出。使用
-g
参数时,请注意**
--limit
是按时间桶限制**——若需要整个时间窗口的总计数据,请省略
-g

Cache hit rate

缓存命中率

Start here for an overall picture of how well caching is working.
Step 1 — overall split. Group
vercel.request.count
by
cache_result
. Treat
HIT
,
STALE
, and
PRERENDER
as cache-served; focus investigation on
MISS
. Exclude
BYPASS
and
(not set)
when computing a hit rate over cacheable traffic (see Debugging BYPASS traffic).
STALE
means stale-while-revalidate is working — dig into revalidation frequency in Analyzing ISR costs, not here.
bash
vercel metrics vercel.request.count -S <team> -p <project> \
  -f "environment eq 'production'" --group-by cache_result --since 24h
Step 2 — where misses concentrate. Split the
MISS
bucket (and optionally
STALE
) by
path_type
, then by
route
or
request_path
:
bash
vercel metrics vercel.request.count -S <team> -p <project> \
  -f "environment eq 'production' and cache_result eq 'MISS'" \
  --group-by path_type --since 24h

vercel metrics vercel.request.count -S <team> -p <project> \
  -f "environment eq 'production' and cache_result eq 'MISS' and path_type eq 'prerender'" \
  --group-by request_path --since 24h
What to expect:
prerender
routes (static shells, ISR pages) should show a high share of
HIT
/
PRERENDER
. A
prerender
path with a disproportionate
MISS
count is your short list for per-path header inspection (
curl
above) and code review.
streaming_func
routes render dynamically by default, but you can still cache them with
Cache-Control
headers — matching requests are cached on the CDN. Each cache entry varies by
Vary
headers (cookies, RSC, etc.) as well as path and query parameters, so expect more cache keys and a lower hit rate than a fully static
prerender
route.
从整体缓存效果入手。
步骤1——整体拆分。按
cache_result
分组统计
vercel.request.count
。将
HIT
STALE
PRERENDER
视为缓存命中;重点排查
MISS
。计算可缓存流量的命中率时,需排除
BYPASS
(not set)
(详见调试BYPASS流量)。
STALE
意味着stale-while-revalidate策略正常工作——需在分析ISR成本中排查重新验证频率,而非此处。
bash
vercel metrics vercel.request.count -S <team> -p <project> \
  -f "environment eq 'production'" --group-by cache_result --since 24h
步骤2——未命中集中区域。将
MISS
(可选包含
STALE
)按
path_type
拆分,再按
route
request_path
拆分:
bash
vercel metrics vercel.request.count -S <team> -p <project> \
  -f "environment eq 'production' and cache_result eq 'MISS'" \
  --group-by path_type --since 24h

vercel metrics vercel.request.count -S <team> -p <project> \
  -f "environment eq 'production' and cache_result eq 'MISS' and path_type eq 'prerender'" \
  --group-by request_path --since 24h
预期结果
prerender
路由(静态外壳、ISR页面)应显示较高的
HIT
/
PRERENDER
占比。若某个
prerender
路径的
MISS
占比过高,需优先对其进行路径头检查(上述
curl
命令)和代码审查。
streaming_func
路由默认动态渲染,但仍可通过
Cache-Control
头进行缓存——匹配的请求会被缓存到CDN。每个缓存条目会根据
Vary
头(Cookie、RSC等)、路径和查询参数区分,因此缓存键数量更多,命中率比完全静态的
prerender
路由更低。

Analyzing ISR costs

分析ISR成本

Once you know hit rate, quantify ISR spend and whether revalidation — not traffic volume — is driving it.
Utilization vs. ISR billing. Utilization is
vercel.request.count
— total request volume. ISR cost is billed separately in 8 KB units:
read_units
when the regional CDN misses and falls through to the ISR cache, and
write_units
on every revalidation/regeneration. The regional CDN shields ISR heavily — most requests never touch the ISR layer, so read_units will be far below request count. Do not compare read_units to write_units as a utilization check; focus on write_units (revalidation cost) and how they relate to total traffic.
bash
vercel metrics vercel.request.count -S <team> -p <project> -a sum --since 24h
vercel metrics vercel.isr_operation.write_units -S <team> -p <project> -a sum --since 24h
Which routes revalidate most. Break write units down by
route
and
request_path
to find paths that regenerate often relative to traffic:
bash
vercel metrics vercel.isr_operation.write_units -S <team> -p <project> \
  -a sum --group-by route --since 24h

vercel metrics vercel.isr_operation.write_units -S <team> -p <project> \
  -a sum --group-by request_path --since 24h
Regeneration vs. serving. Group write units by
path_type
— concentration in
background_func
confirms revalidation (not per-request dynamic work) is the cost driver.
Time-based vs. tag-based revalidation. Time-based intervals regenerate on a schedule whether or not content changed — often inefficient. Tag-based on-demand revalidation is usually better, but an overly broad tag has a large blast radius: one invalidate drops every entry that carries it.
  • Tag blast radius — group write units by
    cache_tags
    . If many unrelated routes show near-identical write counts, a shared hot tag is invalidating them in lockstep (e.g. every blog post rewriting at the same rate because they share one broad
    blogPost
    tag):
bash
vercel metrics vercel.isr_operation.write_units -S <team> -p <project> \
  -a sum --group-by cache_tags --since 24h
  • What triggered revalidation — group
    vercel.request.count
    by
    triggering_tag
    to see which tags fire most often (
    triggering_tag
    is on request count only, not ISR operation metrics. It is one of the tags that triggered the page to be stale):
bash
vercel metrics vercel.request.count -S <team> -p <project> \
  -f "triggering_tag ne null" --group-by triggering_tag --since 24h
Tags with a large blast radius that revalidate frequently are the usual root cause of high write_units. Prefer granular tags (
product-${id}
) and on-demand invalidation over short time-based intervals for event-driven content.
Confirm in code. Metrics tell you which tag is hot; the repo tells you why. Grep for the tag's invalidation call site —
revalidateTag(
,
invalidateByTag(
,
updateTag(
,
dangerouslyDeleteByTag(
— and read the trigger. A CMS webhook or a sync cron that invalidates a broad tag on every event (instead of a specific
${type}:${id}
) is the classic amplifier.
了解命中率后,量化ISR支出,并确认是重新验证而非流量规模导致成本上升。
使用率与ISR计费使用率
vercel.request.count
——总请求量。ISR成本按8 KB单位单独计费:当区域CDN未命中并回退到ISR缓存时产生
read_units
,每次重新验证/重新生成时产生
write_units
。区域CDN对ISR的屏蔽作用很强——大多数请求不会触及ISR层级,因此read_units会远低于请求量。不要将read_units与write_units对比来检查使用率;重点关注write_units(重新验证成本)及其与总流量的关系。
bash
vercel metrics vercel.request.count -S <team> -p <project> -a sum --since 24h
vercel metrics vercel.isr_operation.write_units -S <team> -p <project> -a sum --since 24h
重新验证最频繁的路由。按
route
request_path
拆分write_units,找出相对于流量而言重新生成频率较高的路径:
bash
vercel metrics vercel.isr_operation.write_units -S <team> -p <project> \
  -a sum --group-by route --since 24h

vercel metrics vercel.isr_operation.write_units -S <team> -p <project> \
  -a sum --group-by request_path --since 24h
重新生成与服务。按
path_type
分组统计write_units——若集中在
background_func
,则确认是重新验证(而非单请求动态处理)导致成本上升。
基于时间与基于标签的重新验证。基于时间的间隔会按计划重新生成内容,无论内容是否变化——通常效率较低。基于标签的按需重新验证通常更优,但过于宽泛的标签会导致影响范围过大:一次失效操作会清除所有关联条目。
  • 标签影响范围——按
    cache_tags
    分组统计write_units。若许多不相关路由的write_units数量几乎相同,则说明存在一个共享的高频标签,导致它们同步失效(例如,所有博客文章因共享一个宽泛的
    blogPost
    标签而以相同频率重新生成):
bash
vercel metrics vercel.isr_operation.write_units -S <team> -p <project> \
  -a sum --group-by cache_tags --since 24h
  • 重新验证触发源——按
    triggering_tag
    分组统计
    vercel.request.count
    ,查看哪些标签触发频率最高(
    triggering_tag
    仅存在于请求计数指标中,不存在于ISR操作指标中,是导致页面过期的标签之一):
bash
vercel metrics vercel.request.count -S <team> -p <project> \
  -f "triggering_tag ne null" --group-by triggering_tag --since 24h
影响范围大且重新验证频繁的标签通常是write_units过高的根本原因。对于事件驱动型内容,建议优先使用细粒度标签(如
product-${id}
)和按需失效,而非短间隔的基于时间的重新验证。
代码确认。指标会告诉你哪个标签是高频触发源,而代码仓库会告诉你原因。搜索该标签的失效调用位置——
revalidateTag(
invalidateByTag(
updateTag(
dangerouslyDeleteByTag(
——并查看触发逻辑。典型问题是CMS webhook或同步定时任务在每次事件时失效一个宽泛的标签(而非特定的
${type}:${id}
),导致放大成本。

Debugging BYPASS traffic

调试BYPASS流量

The largest legitimate sources of
BYPASS
are Draft Mode and SEO crawlers. Draft Mode must bypass cache so editors see live content. SEO bots must receive the full response — especially on PPR routes where the static shell and dynamic holes are assembled at request time — so crawlers index what users actually see. That BYPASS is expected, not a misconfiguration.
Before tuning headers or revalidate intervals, confirm what's left after those two buckets:
bash
vercel metrics vercel.request.count -S <team> -p <project> \
  -f "cache_result eq 'BYPASS'" --group-by bot_category --since 24h

vercel metrics vercel.request.count -S <team> -p <project> \
  -f "cache_result eq 'BYPASS'" --group-by user_agent --since 24h

vercel metrics vercel.request.count -S <team> -p <project> \
  -f "cache_result eq 'BYPASS'" --group-by request_method --since 24h
The Firewall/WAF with the
vercel-firewall
skill can be used to manage verified SEO crawlers, block abusive bots, and rate-limit junk traffic before it distorts your hit-rate picture.
BYPASS
的主要合法来源是草稿模式(Draft Mode)SEO爬虫。草稿模式必须绕过缓存,以便编辑者查看实时内容。SEO机器人必须接收完整响应——尤其是在PPR路由中,静态外壳和动态部分会在请求时组装——因此爬虫会索引用户实际看到的内容。这类BYPASS是预期行为,并非配置错误。
在调整头信息或重新验证间隔之前,先确认排除这两类流量后的剩余情况:
bash
vercel metrics vercel.request.count -S <team> -p <project> \
  -f "cache_result eq 'BYPASS'" --group-by bot_category --since 24h

vercel metrics vercel.request.count -S <team> -p <project> \
  -f "cache_result eq 'BYPASS'" --group-by user_agent --since 24h

vercel metrics vercel.request.count -S <team> -p <project> \
  -f "cache_result eq 'BYPASS'" --group-by request_method --since 24h
搭配
vercel-firewall
技能的防火墙/WAF可用于管理已验证的SEO爬虫、阻止恶意机器人,并在垃圾流量影响命中率之前对其进行限流。

Reducing ISR cost

降低ISR成本

  • Prefer tag-based over time-based revalidation. Replace short
    revalidate
    intervals with on-demand
    revalidateTag
    /
    invalidateByTag
    when content changes — time-based regeneration runs whether or not anything changed. If using Cache Components, analyze
    cacheLife
    calls with the
    next-cache-components
    skill.
  • Scope tags to specific IDs. Invalidate
    blogPost:<id>
    , not a generic
    blogPost
    /
    page
    tag — one broad invalidate regenerates everything that carries it.
  • Tune the revalidate interval where your framework declares it (Next.js
    revalidate
    /
    cacheLife
    , SvelteKit
    isr
    , Nuxt
    routeRules
    , Astro). For Next.js Cache Components, see the
    next-cache-components
    skill.
  • Use
    CDN-Cache-Control
    headers to cache dynamic functions.
  • 优先使用基于标签的重新验证。将短间隔的
    revalidate
    替换为内容变化时的按需
    revalidateTag
    /
    invalidateByTag
    ——基于时间的重新生成无论内容是否变化都会运行。若使用Cache Components,请使用
    next-cache-components
    技能分析
    cacheLife
    调用。
  • 将标签限定到特定ID。失效
    blogPost:<id>
    ,而非通用的
    blogPost
    /
    page
    标签——一次宽泛的失效操作会重新生成所有关联条目。
  • 在框架声明处调整重新验证间隔(Next.js的
    revalidate
    /
    cacheLife
    、SvelteKit的
    isr
    、Nuxt的
    routeRules
    、Astro的对应配置)。对于Next.js Cache Components,请查看
    next-cache-components
    技能。
  • 使用
    CDN-Cache-Control
    头缓存动态函数。

Inspect one path

检查单个路径

bash
curl -sSI https://<host>/<path> | grep -iE 'x-vercel-cache|x-matched-path|cache-control|vary|age|set-cookie'
This zero-dependency first reach shows the status (
x-vercel-cache
), the cache directives (
Cache-Control
/
CDN-Cache-Control
/
Vercel-CDN-Cache-Control
), and — crucially —
x-matched-path
, which reveals rewrites like
/precomputed/exp~.../...
that expose experiment/flag precomputation.
vary
flags personalization (RSC, cookies);
set-cookie
forces
BYPASS
. For a per-phase timing breakdown,
vercel httpstat /some/path
(CLI v48.9.0+; needs the
httpstat
tool installed) adds latency stats. A path that should cache but shows
MISS
/
BYPASS
usually has
private
,
no-store
,
max-age=0
, a per-request input (cookies/headers/
searchParams
), or an uncacheable method (see FAQ).
Inspect one request. When metrics or headers give you a request ID, pull the full log record:
bash
vercel logs --request-id <request-id> --json
Use
--json
so the agent can parse cache status, path, and timing fields programmatically.
bash
curl -sSI https://<host>/<path> | grep -iE 'x-vercel-cache|x-matched-path|cache-control|vary|age|set-cookie'
这个零依赖的方法可查看缓存状态(
x-vercel-cache
)、缓存指令(
Cache-Control
/
CDN-Cache-Control
/
Vercel-CDN-Cache-Control
),以及至关重要的**
x-matched-path
**——它会显示重写路径(如
/precomputed/exp~.../...
),暴露实验/特性标志的预计算逻辑。
vary
标志表示个性化内容(RSC、Cookie);
set-cookie
会强制触发
BYPASS
。如需查看各阶段的时间 breakdown,
vercel httpstat /some/path
(CLI v48.9.0+;需安装
httpstat
工具)可添加延迟统计。若某个应该缓存的路径显示
MISS
/
BYPASS
,通常是因为设置了
private
no-store
max-age=0
、单请求输入(Cookie/头信息/
searchParams
)或不可缓存方法(详见FAQ)。
检查单个请求。当指标或头信息提供请求ID时,可拉取完整日志记录:
bash
vercel logs --request-id <request-id> --json
使用
--json
参数可让工具程序解析缓存状态、路径和时间字段。

FAQ

FAQ

  • What are prerender variant misses? When a route uses a dynamic param, each distinct cache-key variant is prerendered and cached separately, so each variant misses on its first hit per region and low-traffic ones rarely stay warm. The most common modern cause is feature-flag / experiment precomputation — middleware picks a variant per request (
    /precomputed/exp~.../...
    paths), and flags × routes × PPR segments multiply into thousands of ISR entries (also a middleware-invocation cost). Fix: collapse the variant matrix (retire finished experiments), or accept the cost.
  • Does PPR avoid function invocations? No — a PPR route has dynamic holes by definition, so the cached shell hit still runs the function to fill them. (A route with no holes is just ISR and serves a pure
    prerender
    HIT — see Key concepts.)
  • Why are there more function invocations than PPR requests? PPR requests have a static shell and a dynamic function invocation. When the static shell needs to be regenerated, it incurs a function invocation on top of the dynamic function for the content.
  • 什么是预渲染变体未命中?当路由使用动态参数时,每个不同的缓存键变体都会被预渲染并单独缓存,因此每个变体在每个区域的首次请求都会未命中,低流量变体很难保持预热状态。最常见的现代原因是特性标志/实验预计算——中间件会针对每个请求选择一个变体(
    /precomputed/exp~.../...
    路径),标志×路由×PPR片段会生成数千个ISR条目(同时也会增加中间件调用成本)。修复方案:合并变体矩阵(结束已完成的实验),或接受该成本。
  • **PPR是否能避免函数调用?**不能——PPR路由本质上包含动态部分,因此命中静态外壳后仍会运行函数来填充动态内容。(无动态部分的路由完全等同于ISR,会返回纯
    prerender
    命中——详见关键概念。)
  • **为什么函数调用次数多于PPR请求次数?**PPR请求包含静态外壳和动态函数调用。当静态外壳需要重新生成时,除了内容的动态函数调用外,还会额外触发一次函数调用。

Related skills

相关技能

  • vercel-firewall
    — manage verified SEO crawlers, block abusive bots, and rate-limit junk BYPASS traffic.
  • runtime-cache
    — caching data between your function and a backend (per-region key-value / data cache). A different layer from the CDN/ISR caches; use it to cache an API response or query result inside a function.
  • next-cache-components
    — Next.js
    use cache
    ,
    cacheLife
    ,
    cacheTag
    , and
    revalidate
    tuning (one framework's ISR/PPR controls).
  • vercel-firewall
    ——管理已验证的SEO爬虫、阻止恶意机器人,并对垃圾BYPASS流量进行限流。
  • runtime-cache
    ——在函数与后端之间缓存数据(区域级键值/数据缓存)。这是与CDN/ISR缓存不同的层级;可用于在函数内部缓存API响应或查询结果。
  • next-cache-components
    ——Next.js的
    use cache
    cacheLife
    cacheTag
    revalidate
    调优(某一框架的ISR/PPR控制)。

References:

参考资料: