Skip to content

[deployment/web] Add --web-content-hash, Cache-Control, Overlay Deployment, and precache_manifest.json guidance for Flutter 3.50 #13825

Description

@kevmoo

Note

Target Release: Flutter 3.50 (Q4 2026 Stable)
All implementation phases for flutter build web --web-content-hash (Umbrella: flutter/flutter#149031) have landed on master for the Flutter 3.50 branch cut:

Page URL

Problem

With flutter build web --web-content-hash shipping in Flutter 3.50 (flutter/flutter#149031), the Flutter Web deployment and FAQ pages need to be updated (cc @parlough @sfshaza2):

  1. Outdated FAQ statement: sites/docs/src/content/platform-integration/web/faq.md#L180-L181 still states "Flutter doesn't currently support appending build IDs to resources automatically" and only shows the unhashed max-age=0, must-revalidate firebase.json rule (L197-L229).
  2. Missing --web-content-hash, Cache-Control, Overlay Deployment, and precache_manifest.json guidance: sites/docs/src/content/deployment/web.md does not yet document --web-content-hash, split Cache-Control rules for hashed vs. unhashed files, overlay deployments across releases, or custom service worker integration via precache_manifest.json.
Detailed page breakdown & affected targets (AI-assisted)

Proposed Content

1. sites/docs/src/content/platform-integration/web/faq.md (https://docs.flutter.dev/platform-integration/web/faq)

  • Replace L180-L181 ("Flutter doesn't currently support appending build IDs to resources automatically") with guidance on running flutter build web --web-content-hash, which automatically embeds 8-character MD5 content hashes into compiled entrypoints (main.dart.<hash>.js, .wasm, .mjs), their .map source maps, and physical assets under build/web/assets/** (with transparent runtime resolution in AssetManager).
  • Under ### How do I configure my cache headers? (L183-L236), add the firebase.json configuration for --web-content-hash builds that pairs max-age=0, must-revalidate on bootstrap/manifest files with public, max-age=31536000, immutable on hashed entrypoints and hashed assets:
{
  "hosting": {
    "public": "build/web",
    "ignore": ["**/*.map"],
    "headers": [
      {
        "source": "**",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=0, must-revalidate"
          }
        ]
      },
      {
        "regex": "^/main\\.dart\\.[0-9a-f]{8}\\.(js|wasm|mjs)$",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "public, max-age=31536000, immutable"
          }
        ]
      },
      {
        "regex": "^/assets/.+\\.[0-9a-f]{8}\\.[A-Za-z0-9]+$",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "public, max-age=31536000, immutable"
          }
        ]
      },
      {
        "source": "404.html",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=0, must-revalidate"
          }
        ]
      }
    ],
    "rewrites": [
      {
        "source": "!(/assets/**|/canvaskit/**|/icons/**|/main.dart.*)",
        "destination": "/index.html"
      }
    ]
  }
}

2. sites/docs/src/content/deployment/web.md (https://docs.flutter.dev/deployment/web)

Add a Web server caching and --web-content-hash section covering:

  1. Hashed vs. Unhashed Build Outputs:
    • Immutable (public, max-age=31536000, immutable): main.dart.<hash>.js, main.dart.<hash>.wasm, main.dart.<hash>.mjs, their .map files (if deployed internally), and all hashed asset files under assets/** (assets/FontManifest.<hash>.json is not hashed; see below).
    • Revalidate on Every Load (max-age=0, must-revalidate or no-cache): index.html, flutter_bootstrap.js, flutter.js, manifest.json, version.json, 404.html, top-level manifests (assets/AssetManifest.bin, assets/AssetManifest.bin.json, assets/FontManifest.json, assets/NOTICES), canvaskit/**, and deferred .part.js chunks.
  2. Overlay Deployments (Zero-Downtime Rollouts for Active Tabs):
    • When deploying a new release N, an already-open browser tab running release N-1 may lazily fetch an image, font, or asset with release N-1's content hash.
    • To prevent mid-session 404 errors during rollout, retain at least the previous release's (N-1) hashed files alongside the new release's (N) hashed files in your CDN/storage bucket (or prune old hashes after a 24–72 hour grace window) while atomically updating index.html, flutter_bootstrap.js, and AssetManifest.bin.
  3. Custom Service Workers (build/web/precache_manifest.json):
    • When --web-content-hash is enabled, flutter build web generates build/web/precache_manifest.json ({"version": 1, "entries": [{"url": "...", "revision": "...", "size": ..., "urlHashed": true|false}]}) for consumption by Workbox or custom PWA service workers.
  4. Current Limitations:
    • --web-content-hash is currently mutually exclusive with --enable-wasm-deferred-loading (flutter/flutter#191917).

3. sites/docs/src/content/platform-integration/web/initialization.md (https://docs.flutter.dev/platform-integration/web/initialization)

  • Note under ## Write a custom bootstrap script (L83-L103) that --web-content-hash injects the hashed entrypoint filenames (mainJsPath, jsSupportRuntimePath, wasmPath) into {{flutter_build_config}}. Custom web/index.html or web/flutter_bootstrap.js files must use {{flutter_build_config}} with _flutter.loader.load() rather than hardcoding "main.dart.js" or calling the deprecated loadEntrypoint API.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    a.faqRelates to the FAQ section of Flutter.deva.rn.release-notesRelates to Flutter release notes found on docs.flutter.devd.new-featureAdds new Flutter contentdev.deploymentRelates to deploying Flutter app section of Flutter.deve1-hoursEffort: < 8 hrsfrom.teamReported by Dash docs team memberp1-highMajor but not urgent concern: Resolve in months. Update each month.target.webTarget apps on the web platform

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions