Skip to content

Understanding Implicit Tags and Revalidation in Next.js

Arseny edited this page Sep 18, 2024 · 3 revisions

Understanding Implicit Tags and Revalidation in Next.js

Next.js's caching system, particularly with the App Router, can be complex due to its internal mechanisms and how it handles cache invalidation. This guide aims to clarify the concepts of implicit tags, the role of NEXT_CACHE_IMPLICIT_TAG_ID, and the revalidation process. This should help you make informed decisions and contribute effectively to the community.

Table of Contents

  1. Implicit Tags
  2. NEXT_CACHE_IMPLICIT_TAG_ID: "_N_T_"
  3. Understanding get and revalidateTag
  4. Step-by-Step Explanation of Revalidation

Implicit Tags

What Are Implicit Tags?

Implicit tags are automatically generated cache tags used internally by Next.js to manage cache invalidation for pages and layouts in the App Router. They help Next.js determine which cache entries must be invalidated when certain pages or layouts change.

How Are Implicit Tags Generated?

Implicit tags are generated based on the routing hierarchy of your Next.js application. For example, for a page at /user/[id]/page.js, the implicit tags for /user/123 will look like:

  • _N_T_/layout
  • _N_T_/user/layout
  • _N_T_/user/[id]/layout
  • _N_T_/user/[id]/page
  • _N_T_/user/123

These tags represent the nested layouts and pages, allowing Next.js to manage associated cache entries.

Relation to fetch() and unstable_cache() Tags

  • Fetch Tags: When using fetch() with caching options, you can specify explicit tags for cache invalidation.
  • unstable_cache Tags: Similarly, unstable_cache() allows for explicit tagging.
  • Implicit Tags: These are additional, internally managed tags that do not include or replace your explicit tags. They work alongside them to ensure the integrity of the caching system.

NEXT_CACHE_IMPLICIT_TAG_ID: "_N_T_"

Purpose of NEXT_CACHE_IMPLICIT_TAG_ID

NEXT_CACHE_IMPLICIT_TAG_ID is a unique identifier used by Next.js to prefix implicit tags. The default value is "_N_T_". This prefix helps distinguish implicit tags from user-defined tags and ensures internal cache management processes function correctly.

Stability and Public API Status

NEXT_CACHE_IMPLICIT_TAG_ID is considered an internal constant and is not part of the public API. It is intended for use within Next.js' core and may change without notice in future releases.

Special Treatment of Implicit Tags

Implicit tags require different handling because:

  • Internal Consistency: They ensure the internal caching mechanisms of Next.js operate without interference from user-defined tags.
  • Avoiding Conflicts: Using a unique prefix prevents accidental collisions with tags you might define in your application.

Understanding get and revalidateTag

Revalidation on get operation

When you call revalidateTag, it signals Next.js that specific cached data associated with that tag must be revalidated. However, the actual cache invalidation doesn't happen immediately. Instead, it occurs the next time a get operation accesses the cache. This deferred invalidation optimizes performance by avoiding unnecessary data fetching until it's needed.

Internal Mechanisms

  1. Mark for Revalidation: revalidateTag adds the specified tag to a list of tags that require revalidation.
  2. Deferred Invalidation: The cache entry remains valid until the next get operation checks the cache.
  3. Cache Check: Upon a get, Next.js checks if any associated tags are marked for revalidation.
  4. Invalidation and Refetch: If so, Next.js invalidates the cache entry and fetches fresh data.

Step-by-Step Explanation of Revalidation

Below is a detailed walkthrough of how revalidation works in Next.js, including implicit tags.

  1. Initial Page Load

    • User Visits Page: A user accesses /user/123.
    • Data Fetching: Next.js fetches data using fetch() or unstable_cache(), caching it with explicit tags (if provided) and implicit tags.
    • Caching:
      • Fetch Cache: Stores the fetched data associated with any explicit tags and implicit tags.
      • Page Cache: Stores the rendered page output.
  2. Triggering Revalidation

    • Data Change: The data for user/123 changes on the server.
    • Revalidation Request: An API route or background process calls revalidatePath('/user/123').
    • Revalidation Process:
      • Implicit Tag Identification: Next.js identifies implicit tags associated with /user/123, such as _N_T_/user/[id]/page.
      • Tag Marking: These implicit tags are marked for revalidation.
      • Page Cache Deletion: The page cache for /user/123 is invalidated immediately.
  3. Subsequent Page Load

    • User Revisits Page: The user accesses /user/123 again.
    • Cache Access:
      • Page Cache Miss: Since the page cache was invalidated, Next.js needs to re-render the page.
      • Fetch Cache Check: Next.js calls get to access the fetch cache.
    • Deferred Revalidation:
      • Tag Check: Next.js checks if the implicit tags associated with the fetch cache are marked for revalidation.
      • Cache Invalidation: If so, the fetch cache is invalidated.
      • Data Refetch: Next.js fetches fresh data from the server.
    • Page Rendering: The page is re-rendered with the updated data and cached for future requests.

Sequence Diagram

Note: CacheHandler and TagStore are kept separate for clarity. In practice, TagStore is stored within the cache.

sequenceDiagram
    participant User
    participant Next.js Server
    participant Backend
    participant CacheHandler
    participant TagStore

    User->>Next.js Server: Request /user/123
    Next.js Server->>Backend: Fetch data
    Backend-->>Next.js Server: Return data
    Next.js Server->>CacheHandler: Save fetch and page cache with tags
    Next.js Server-->>User: Serve page

    User->>Next.js Server: Calls revalidatePath('/user/123')
    Next.js Server->>TagStore: Mark implicit tags for /user/123
    Next.js Server->>CacheHandler: Invalidate page cache

    User->>Next.js Server: Request /user/123 again
    Next.js Server->>CacheHandler: Check page cache (miss)
    Next.js Server->>CacheHandler: Check fetch cache
    CacheHandler->>TagStore: Are tags marked for revalidation?
    TagStore-->>CacheHandler: Yes
    CacheHandler->>CacheHandler: Invalidate fetch cache
    Next.js Server->>Backend: Fetch fresh data
    Backend-->>Next.js Server: Return updated data
    Next.js Server->>CacheHandler: Save new fetch and page cache
    Next.js Server-->>User: Serve updated page
Loading