惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Troy Hunt's Blog
P
Proofpoint News Feed
Help Net Security
Help Net Security
T
The Exploit Database - CXSecurity.com
Recent Commits to openclaw:main
Recent Commits to openclaw:main
NISL@THU
NISL@THU
Forbes - Security
Forbes - Security
N
News and Events Feed by Topic
C
CERT Recently Published Vulnerability Notes
Simon Willison's Weblog
Simon Willison's Weblog
Hacker News: Ask HN
Hacker News: Ask HN
P
Privacy International News Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Hacker News - Newest:
Hacker News - Newest: "LLM"
云风的 BLOG
云风的 BLOG
博客园 - 【当耐特】
S
Secure Thoughts
爱范儿
爱范儿
Jina AI
Jina AI
H
Heimdal Security Blog
量子位
罗磊的独立博客
人人都是产品经理
人人都是产品经理
T
Threat Research - Cisco Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Cisco Talos Blog
Cisco Talos Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
MyScale Blog
MyScale Blog
T
Tor Project blog
博客园_首页
T
Tenable Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Threatpost
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Security Archives - TechRepublic
Security Archives - TechRepublic
TaoSecurity Blog
TaoSecurity Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Latest news
Latest news
AWS News Blog
AWS News Blog
Y
Y Combinator Blog
Martin Fowler
Martin Fowler
Last Week in AI
Last Week in AI
V
Visual Studio Blog
The Hacker News
The Hacker News
I
Intezer
L
LINUX DO - 最新话题
L
LangChain Blog
W
WeLiveSecurity

Next.js Blog

July 2026 Security Release Next.js Security Release and Our Next Patch Release Turbopack: What's New in Next.js 16.3 Next.js 16.3: AI Improvements Next.js 16.3: Instant Navigations Next.js Across Platforms: Adapters, OpenNext, and Our Commitments Next.js 16.2: AI Improvements Next.js 16.2 Turbopack: What's New in Next.js 16.2 Building Next.js for an agentic future Inside Turbopack: Building Faster by Building Less Next.js 16.1 Next.js Security Update: December 11, 2025 Security Advisory: CVE-2025-66478 Next.js 16 Next.js 16 (beta) Next.js 15.5 Next.js 15.4 Next.js 15.3 Building APIs with Next.js Next.js 15.2 Composable Caching with Next.js Next.js 15.1 Next.js 15 Turbopack Dev is Now Stable Next.js 15 RC 2 Next.js 15 RC Next.js 14.2 Next.js 14.1 Next.js 14 How to Think About Security in Next.js Next.js 13.5 Next.js App Router Update Next.js 13.4 Next.js 13.3 Next.js 13.2 Next.js 13.1 Next.js 13 Next.js 12.3 Next.js 12.2 Layouts RFC Next.js 12.1 Next.js 12 Next.js 11.1 Next.js 11 Next.js 10.2 Next.js 10.1 Incrementally Adopting Next.js Next.js 10 Next.js 9.5 Next.js 9.4 Next.js 9.3 Next.js 9.2 Next.js 9.1.7 Introducing Create Next App Next.js 9.1 Next.js 9.0.7 Next.js 9 Next.js 8.1 Next.js 8.0.4 Styling Next.js with Styled JSX Next.js 8 Webpack Memory Improvements Next.js 8 Next.js 7 Next.js 6.1 Next.js 6 and Nextjs.org Next.js 5.1: Faster Page Resolution, Environment Config & More Next.js 5: Universal Webpack, CSS Imports, Plugins and Zones
Our Journey with Caching
Sebastian Markbåge · 2024-10-24 · via Next.js Blog

Frontend performance can be hard to get right. Even in highly optimized apps, the most common culprit by far is client-server waterfalls. When introducing Next.js App Router, we knew we wanted to solve this issue. To do that, we needed to move client-server REST fetches to the server using React Server Components in a single roundtrip. This meant the server had to sometimes be dynamic, sacrificing the great initial loading performance of Jamstack. We built partial prerendering to solve this tradeoff and have the best of both worlds.

However, along the way, the developer experience suffered due to the caching defaults and controls we provided. The default for fetch() changed to favor performance by caching by default, but quick prototyping and highly dynamic apps suffered. We didn't provide enough control over local database access that wasn't using fetch(). We had unstable_cache(), but it wasn't ergonomic. This led to the need for segment-level configs, such as export const dynamic, runtime, fetchCache, dynamicParams, revalidate = ..., as an escape hatch.

We'll continue supporting that for backward compatibility, of course. But for a moment, I'd like you to forget about all that. We think we have an idea for something simpler.

We've been cooking on a new experimental mode that builds on just two concepts: <Suspense> and use cache.

Choose your adventure

The first thing you'll notice is that when you add data to your components, you will now get an error.

To use data, cookies, headers, current time or random values, you now have a choice: do you want the data to be cached (server or client-side) or executed on every request? I'm using fetch() as an example, but this applies to any async Node API, such as databases or timers.

Dynamic

If you're still iterating or building a highly dynamic dashboard, you can wrap the component in a <Suspense> boundary. <Suspense> opts into dynamic data fetching and streaming.

You can also do this in your root layout or use loading.tsx.

This ensures that the shell of your app remains instant. You can continue adding more data inside your Page, knowing it will all be dynamic by default. Nothing is cached by default. No more hidden caches.

Static

If you're building something static and don't want to use dynamic functionality, you can use the new use cache directive.

By marking the Page with use cache, you're indicating that the entire segment should be cached. This means any data you fetch can now be cached, allowing the page to be statically rendered. No <Suspense> boundary is used for static content. You can add more data to the page, and it will all be cached.

Partial

You can also mix and match. For example, you can put use cache in your root layout to ensure it is cached. Each layout or page can be cached independently.

While using dynamic data within a specific Page:

Cached functions

When using a hybrid approach like this, it might be more convenient to add caching closer to the API calls.

You can add use cache to any async function, just like use server. Think of it as a Server Action but instead of calling a Server you're calling a Cache. It supports the same rich types of arguments and return values beyond just JSON. The cache key automatically includes any arguments and closures, so you don't need to specify a cache key manually.

Since no other data was used in this layout, it can remain static. A benefit of this approach is that if you accidentally add new dynamic data to the layout, it will trigger an error during the build, forcing you to make a new choice. If you add use cache to the entire layout, it will be cached with no error. Which approach you choose depends on your use case.

Tagging a cache

If you want to explicitly clear a cache entry by tag, you can use the new cacheTag() API inside the use cache function.

Then, just call revalidateTag('my-tag') from a Server Action as before.

Since this API can be called after data loading, you can now use data to tag your cache entries.

Defining the lifetime of a cache

If you want to control how long a particular entry or page should live in the cache, you can use the cacheLife() API:

By default, it accepts the following values:

  • "seconds"
  • "minutes"
  • "hours"
  • "days"
  • "weeks"
  • "max"

Choose a rough range that bests fits your use case. No need to specify an exact number and calculate how many seconds (or was it milliseconds?) are in a week. However, you can also specify specific values or configure your own named cache profiles.

In addition to revalidate, this API can control the stale time of the client cache as well as expire, which dictates when a Page should expire if it hasn't had much traffic for a while.

Experimental

This is still very much an experimental project. It's not production-ready yet and still has missing features and bugs. In particular, we know we need to improve the error stacks for this new type of error. However, if you're feeling adventurous, we'd love your early feedback.

We will publish a more detailed upgrade path. Aside from the early errors, the main breaking change here is undoing the default caching of fetch(). That said, we recommend experimenting only on greenfield projects at this early experimental stage. If it pans out well we hope to ship an opt-in version in a minor and make it the default in a future major.

To play with it, you must be on the canary version of Next.js:

You must also enable the experimental dynamicIO flag in next.config.ts:

Read more about use cache, cacheLife, and cacheTag in our documentation.