You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[deployment/web] Add --web-content-hash, Cache-Control, Overlay Deployment, and precache_manifest.json guidance for Flutter 3.50 #13825
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:
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):
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.
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:
Add a Web server caching and --web-content-hash section covering:
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.
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.
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.
Current Limitations:
--web-content-hash is currently mutually exclusive with --enable-wasm-deferred-loading (flutter/flutter#191917).
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.
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 onmasterfor the Flutter 3.50 branch cut:main.dart.<hash>.{js,wasm,mjs}): flutter/flutter#190153build/web/assets/**+AssetManagerlookup): flutter/flutter#191919.wasm.mapsource maps &sourceMappingURLsection rewriting): flutter/flutter#193040, flutter/flutter#193614build/web/precache_manifest.json& public--web-content-hashCLI flag): flutter/flutter#192953Page URL
Problem
With
flutter build web --web-content-hashshipping in Flutter 3.50 (flutter/flutter#149031), the Flutter Web deployment and FAQ pages need to be updated (cc @parlough @sfshaza2):sites/docs/src/content/platform-integration/web/faq.md#L180-L181still states "Flutter doesn't currently support appending build IDs to resources automatically" and only shows the unhashedmax-age=0, must-revalidatefirebase.jsonrule (L197-L229).--web-content-hash,Cache-Control, Overlay Deployment, andprecache_manifest.jsonguidance:sites/docs/src/content/deployment/web.mddoes not yet document--web-content-hash, splitCache-Controlrules for hashed vs. unhashed files, overlay deployments across releases, or custom service worker integration viaprecache_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)L180-L181("Flutter doesn't currently support appending build IDs to resources automatically") with guidance on runningflutter build web --web-content-hash, which automatically embeds 8-character MD5 content hashes into compiled entrypoints (main.dart.<hash>.js,.wasm,.mjs), their.mapsource maps, and physical assets underbuild/web/assets/**(with transparent runtime resolution inAssetManager).### How do I configure my cache headers?(L183-L236), add thefirebase.jsonconfiguration for--web-content-hashbuilds that pairsmax-age=0, must-revalidateon bootstrap/manifest files withpublic, max-age=31536000, immutableon 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-hashsection covering:public, max-age=31536000, immutable):main.dart.<hash>.js,main.dart.<hash>.wasm,main.dart.<hash>.mjs, their.mapfiles (if deployed internally), and all hashed asset files underassets/**(assets/FontManifest.<hash>.jsonis not hashed; see below).max-age=0, must-revalidateorno-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.jschunks.N, an already-open browser tab running releaseN-1may lazily fetch an image, font, or asset with releaseN-1's content hash.404errors 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 updatingindex.html,flutter_bootstrap.js, andAssetManifest.bin.build/web/precache_manifest.json):--web-content-hashis enabled,flutter build webgeneratesbuild/web/precache_manifest.json({"version": 1, "entries": [{"url": "...", "revision": "...", "size": ..., "urlHashed": true|false}]}) for consumption by Workbox or custom PWA service workers.--web-content-hashis 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)## Write a custom bootstrap script(L83-L103) that--web-content-hashinjects the hashed entrypoint filenames (mainJsPath,jsSupportRuntimePath,wasmPath) into{{flutter_build_config}}. Customweb/index.htmlorweb/flutter_bootstrap.jsfiles must use{{flutter_build_config}}with_flutter.loader.load()rather than hardcoding"main.dart.js"or calling the deprecatedloadEntrypointAPI.