Repository navigation
feat(web): resolve raw asset keys via content-hashed manifests and unhide --web-content-hash - #193040
Merged
auto-submit[bot] merged 10 commits intoSep 23, 2026
Merged
Conversation
…bled - Emit build/web/precache_manifest.json in WebServiceWorker when --web-content-hash is enabled, providing deterministic URL, SHA-256 prefix hash, byte size, and urlHashed metadata for custom service workers and PWAs. - Filter non-runtime build artifacts (*.map, *.symbols, *.info.json, dotfiles, flutter_service_worker.js, precache_manifest.json, and canvaskit/** when --web-resources-cdn is active). - Clean up stale precache_manifest.json when --web-content-hash is disabled and prevent Depfile input/output cycles. - Keep --web-content-hash hidden while runtime raw-key asset resolution (rootBundle.load) is completed. Fixes flutter#191916 Part of flutter#149031
…hide --web-content-hash - Content-hash all remaining unhashed files under build/web/assets/ (FontManifest.json, AssetManifest.json, AssetManifest.bin, AssetManifest.bin.json, NOTICES, NOTICES.Z, and shaders/**) in Pass 2 of hashWebAssets. - Inject hashed assetManifest and fontManifest filenames into _flutter.buildConfig in flutter_bootstrap.js and index.html. - Add JSBuildConfig (assetManifest, fontManifest) to JS interop and update fetchFontManifest in web_ui to read _flutter.buildConfig.fontManifest. - Populate ui_web.AssetManager with the content-hashed asset map during initializeEngineServices so raw logical asset keys (rootBundle.load, FragmentProgram.fromAsset, HtmlElementView, custom fetch(assetManager.getAssetUrl(...))) resolve to content-hashed filenames. - Unhide the --web-content-hash CLI flag in flutter build web. Fixes flutter#193031
…ase-2-5 # Conflicts: # packages/flutter_tools/lib/src/web/web_options.dart # packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart
kevmoo
marked this pull request as ready for review
September 21, 2026 18:04
Contributor
There was a problem hiding this comment.
Code Review
This pull request implements runtime asset resolution for web content hashing in Flutter. It updates the web engine to load content-hashed manifests and extra assets from _flutter.buildConfig, and modifies flutter_tools to inject these hashed filenames during release builds. Feedback on the changes suggests supporting single quotes and backticks when parsing JavaScript string literals in _findMatchingClosingBrace, updating the glob patterns in WebReleaseBundle to match the root index.html file, and optimizing JSON decoding in the engine by fusing the UTF-8 and JSON decoders to avoid intermediate string allocations.
… index.html pattern, and fused decoder
mdebbar
previously approved these changes
Sep 22, 2026
…t on deferred wasm modules with --web-content-hash
Contributor
Author
|
@mdebbar one more nod, please! |
mdebbar
approved these changes
Sep 22, 2026
This was referenced Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Completes the
--web-content-hasharchitecture by adding runtime raw-key asset resolution inweb_ui, achieving 100% content-hashing coverage across all files inbuild/web/assets/(eliminating manifest and shader exclusions), preservingAssetManifest.listAssets()andAssetMetadata.main, validating customweb/flutter_bootstrap.js/web/index.htmltemplates, and un-hiding--web-content-hash(--no-web-content-hash) influtter build web --help.Why this is needed
Phase 2 (#191919) and Phase 3 (#192953) renamed physical asset files on disk (
<name>.<hash>.<ext>), rewrote target values insideAssetManifest.bin,AssetManifest.bin.json,AssetManifest.json, andFontManifest.json, and emittedprecache_manifest.json. Two critical gaps remained before exposing--web-content-hashto users:Image.assetresolves variant paths viaAssetManifestbefore callingrootBundle.load(variant.key), direct callers ofrootBundle.load(key)/rootBundle.loadString(key)(PlatformAssetBundle) and third-party web plugins (vector_graphics/flutter_svgAssetBytesLoader,lottie,rive,video_player_web,audioplayers_web) pass the raw declared key (assets/data/config.json) directly toui_web.AssetManager.getAssetUrl(String asset).ui_web.AssetManager.getAssetUrl(asset), raw-key asset fetches requested un-hashed paths (assets/assets/data/config.json) and 404'd on cold caches.build/web/assets/:AssetManifest.*,FontManifest.json,NOTICES,NOTICES.Z, andshaders/**were previously excluded from hashing, which meant a single"source": "assets/**" -> Cache-Control: public, max-age=31536000, immutableCDN rule would freezeAssetManifest.bin.jsonandFontManifest.jsonacross deployments (v1 -> v2).What this PR changes
build/web/assets/Immutability & CleanAssetManifest.listAssets()(packages/flutter_tools/lib/src/web/content_hash.dart):_excludedFilenamesand_excludedDirPrefixesso every file underbuild/web/assets/(includingshaders/**,NOTICES,NOTICES.Z,FontManifest.json,AssetManifest.json,AssetManifest.bin, andAssetManifest.bin.json) is content-hashed on disk.AssetManifest.binandAssetManifest.jsonstrictly limited to user/package manifest entries (storingUri.decodeFullvariant paths soImage.asseton spaced filenames encodes cleanly to%2520rather than triple-encoding to%252520), and passes non-manifest SDK files (NOTICES,shaders/ink_sparkle.frag,shaders/stretch_effect.frag,AssetManifest.bin,AssetManifest.json) via_flutter.buildConfig.extraAssets(~200 bytes) alongside"assetManifest"and"fontManifest".throwToolExit) if customweb/flutter_bootstrap.jsorweb/index.htmltemplates omit{{flutter_build_config}}or contain malformed_flutter.buildConfigassignments.AssetMetadata.main(packages/flutter/lib/src/services/asset_manifest.dart):_AssetManifestBin(asset_manifest.dart) soAssetMetadata.mainremainstruefor the primary 1.0x asset variant when content hashes are embedded in variant filenames..filecacheTracking (packages/flutter_tools/lib/src/build_system/targets/web.dart):{OUTPUT_DIR}/*/index.htmland{OUTPUT_DIR}/flutter_bootstrap.jsinWebReleaseBundle.inputsandWebReleaseBundle.outputswhenwebContentHashis enabled so.filecacherecords post-injection file hashes.web_ui):FlutterJSwithJSBuildConfig(assetManifest,fontManifest,extraAssets) injs_loader.dart.fetchFontManifestinfonts.dartto fetchflutter?.buildConfig?.fontManifest?.toDart ?? 'FontManifest.json'._loadContentHashedAssetManifest(ui_web.assetManager)insideinitializeEngineServices()Future.waitininitialization.dartto registerassetManifest,fontManifest,extraAssets, and decodedAssetManifest.bin.<hash>.jsonmappings in engine-privatesetContentHashedAssetMap/resolveContentHashedAsset(keeping the publicdart:ui_webAssetManagerAPI unchanged).ui_web.AssetManager.getAssetUrl(String asset).--web-content-hash(packages/flutter_tools/lib/src/web/web_options.dart&build_web.dart):hide: truefromWebOptions.webContentHashand notes that localcanvaskit/**(--no-web-resources-cdn) remains un-hashed (urlHashed: falseinprecache_manifest.json).Related Issues
Tests
packages/flutter_tools/test/general.shard/build_system/targets/web_test.dartpackages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart&args_test.dartpackages/flutter/test/services/asset_manifest_test.dartengine/src/flutter/lib/web_ui/test/engine/assets_test.dartChecklist
///).