Next.js Runtime for Netlify

repository·main·Indexed 21 days ago

https://github.com/opennextjs/opennextjs-netlify

The @netlify/plugin-nextjs package manages the build process and runtime environment for Next.js applications deployed on Netlify. It provides native support for Next.js features, including an Edge Runtime based on Deno for Edge Functions, specialized routing utilities for redirects and rewrites, and lifecycle hooks for build cache and asset management. Supports Next.js 13.5+ and Node.js 18+ for v5, with v4 available for legacy environments (Next.js 10-13.4).

Tokens
9.4K
Snippets
36
Records
49
Agent score
75%

What's inside @netlify/plugin-nextjs

  1. Understand the structure of the Edge Runtime directory

    main

    The edge-runtime/ directory is organized into three functional sub-directories:

    1. lib/: Contains files that are imported by the generated edge functions.
    2. shim/: Contains code fragments that are inlined into the generated edge functions. Warning: Do not import files from shim/ anywhere in your application; they are not complete programs and will fail if imported directly.
    3. vendor/: Contains third-party dependencies used by the edge functions. These are pulled in ahead of time to prevent build-time dependencies on package registries.
  2. Understand the Edge Runtime architecture

    main

    The edge-runtime/ directory contains the logic necessary to create Netlify Edge Functions that support Next.js sites.

    Critical Constraint: Unlike the rest of the project which runs in Node.js, files within edge-runtime/ run in Deno. Because of this environment difference, you must never import files from edge-runtime/ into any part of the application outside of this directory.

  3. Install the Next.js Runtime via npm

    main

    If you need to pin the Next.js Runtime to a specific version, you can install it manually using npm.

    1. Install the package as a development dependency:
      npm install -D @netlify/plugin-nextjs
    2. Add the plugin to your netlify.toml file:
      [[plugins]]
        package = "@netlify/plugin-nextjs"
    npm install -D @netlify/plugin-nextjs
    [[plugins]]
      package = "@netlify/plugin-nextjs"
  4. Manage Cache-Control headers for CDN and Browser

    main

    The runtime manages two distinct cache-control mechanisms to prevent leaking Next.js-specific directives (like s-maxage or stale-while-revalidate) to the browser while ensuring the CDN respects them:

    1. cache-control: Sent to the browser. The runtime strips CDN-specific directives and defaults to public, max-age=0, must-revalidate if no browser-safe cache policy is defined.
    2. netlify-cdn-cache-control: Sent to the Netlify CDN. This header contains the full directives, including s-maxage, stale-while-revalidate, and the durable flag.

    If a response is marked as STALE (via x-nextjs-cache), the CDN is instructed not to cache it using: public, max-age=0, must-revalidate, durable.

  5. How the Next.js Runtime manages configuration

    main

    The Next.js Runtime for Netlify uses a specialized configuration object to bridge Next.js settings with the Netlify environment. This configuration is injected into the runtime via the __NEXT_PRIVATE_STANDALONE_CONFIG environment variable.

    Key aspects of this configuration include:

    • Cache Handler: The runtime automatically configures a custom cache handler located at .netlify/dist/run/handlers/cache.cjs to ensure ISR and data caching work correctly on Netlify.
    • Image Optimization: To prevent unhandled rejections caused by Next.js attempting to write to a read-only filesystem, the runtime explicitly sets images.maximumDiskCacheSize to 0. This disables local disk caching in favor of the Netlify Image CDN.
    • In-Memory Caching: The runtime honors the in-memory cache size defined in your next.config.js (via cacheMaxMemorySize or experimental.isrMemoryCacheSize).
  6. Understand TagStaleOrExpiredStatus

    main

    The TagStaleOrExpiredStatus type represents the lifecycle state of a cache tag. This is used to determine if a request should serve cached content, serve stale content, or treat the cache as a MISS.

    Possible states:

    • FRESH: { stale: false, expired: false } - Content is valid.
    • STALE: { stale: true, expired: false, expireAt: number } - Content is stale but still usable; expireAt indicates when it will become fully expired.
    • EXPIRED: { stale: true, expired: true } - Content must be treated as a cache MISS.
    type TagStaleOrExpiredStatus =
      // FRESH
      | { stale: false; expired: false }
      // STALE
      | { stale: true; expired: false; expireAt: number }
      // EXPIRED (should be treated similarly to MISS)
      | { stale: true; expired: true }