Capítulo 282 de 456

Supporting Immutable Static Assets

Core Idea

When enabled, Next.js emits content-addressed static assets under /_next/static/immutable/* that live in a shared namespace across deployments (no ?dpl query param); an adapter opts in via config and uses immutableHash to detect/prevent hash collisions.

Key Concepts

  • config.supportsImmutableAssets: adapter sets this to true in modifyConfig (unless the user explicitly opted out) to signal support for deploying immutable assets.
  • outputs.staticFiles[].immutableHash: full content hash for a static file; present only for immutable assets. Next.js may truncate the filename hash, so this field validates no collision occurred.
  • config.outputHashSalt: salt for content hashes, used to rotate hashes (e.g. after a detected collision).
  • Non-immutable assets: still requested with the ?dpl query parameter, scoped per deployment (e.g. public folder files, or older Next.js versions) — must remain supported alongside immutable ones.

Code Examples

/** @type {import('next').NextAdapter} */
const adapter = {
  name: 'my-custom-adapter',

  async modifyConfig(config, { phase }) {
    if (phase === 'phase-production-build') {
      config.supportsImmutableAssets = config.supportsImmutableAssets ?? true
      // config.outputHashSalt = getSaltForCurrentProject()
    }
    return config
  },

  async onBuildComplete({ outputs }) {
    for (const output of outputs.staticFiles) {
      if (output.immutableHash != null) {
        // Must be requestable at output.pathname even without ?dpl
        uploadOrVerifyImmutableStaticAsset(
          output.filePath,
          output.pathname,
          output.immutableHash
        )
      } else {
        uploadStaticAsset(output.filePath, output.pathname)
      }
    }
  },
}
  • O que demonstra: opt-in em modifyConfig seguido do branch immutable-vs-non-immutable ao processar outputs.staticFiles em onBuildComplete.

Anti-patterns

  • Changing or deleting an immutable asset after deploy: violates the contract; these assets live in a shared cross-deployment namespace and must stay unchanged for as long as any active deployment references them.
  • Dropping support for non-immutable assets: still required for the public folder and older Next.js versions requested with ?dpl.

Key Takeaways

  1. Two-step adapter implementation: (1) opt in via config.supportsImmutableAssets = true in modifyConfig, (2) branch on immutableHash != null in onBuildComplete to decide upload strategy.
  2. Immutable assets must be served at their pathname without the ?dpl query param, since they're shared across deployments by content hash.
  3. outputHashSalt is the escape hatch for rotating hashes after a collision, not a routine config knob.

Connects To

  • ch279 output-types: defines the STATIC_FILE shape including immutableHash.
  • ch274 testing-adapters: the NEXT_SUPPORTS_IMMUTABLE_ASSETS marker the logs script must emit.