Add support for WASM deferred loading.#189308
Conversation
There was a problem hiding this comment.
Code Review
This pull request adds support for multi-module deferred loading in Dart2Wasm. It introduces a wasmDeferredModulesLoader configuration option, adds the --enable-wasm-deferred-loading flag to the web build command, and updates the build system to include deferred Wasm modules and their source maps. Unit tests are also added to verify these changes. Feedback recommends optimizing the default JavaScript loader to enable streaming compilation by passing the fetch promise directly, and hoisting regular expression instantiations out of the file-filtering loop in the build target to prevent performance overhead.
Apply suggestions Co-authored-by: Harry Terkelsen <[email protected]>
| static final RegExp _partWasmRegex = RegExp(r'main\.dart_module[0-9].*\.wasm'); | ||
| static final RegExp _partWasmMapRegex = RegExp(r'main\.dart_module[0-9].*\.wasm\.map'); |
There was a problem hiding this comment.
Since these regular expressions are not anchored, _partWasmRegex.hasMatch('main.dart_module1.wasm.map') will return true because the filename starts with main.dart_module1.wasm.
This means that when compilerConfig.sourceMaps is false, the .wasm.map files will still be incorrectly matched and included in buildFiles by the _partWasmRegex check.
We should anchor them with ^ and $ to prevent substring matches.
| static final RegExp _partWasmRegex = RegExp(r'main\.dart_module[0-9].*\.wasm'); | |
| static final RegExp _partWasmMapRegex = RegExp(r'main\.dart_module[0-9].*\.wasm\.map'); | |
| static final RegExp _partWasmRegex = RegExp(r'^main\.dart_module[0-9].*\.wasm$'); | |
| static final RegExp _partWasmMapRegex = RegExp(r'^main\.dart_module[0-9].*\.wasm\.map$'); |
There was a problem hiding this comment.
Good catch, I updated the regexes, thanks!
harryterkelsen
left a comment
There was a problem hiding this comment.
Thanks for the contribution! I've left a few inline comments on the JS loader options and test structure.
Additionally, I noticed a bug in packages/flutter_tools/lib/src/build_system/targets/web.dart where the regular expressions for matching dynamic modules were unanchored, causing .wasm.map files to be matched as .wasm files. This causes source map files to be included in the build output even when source maps are disabled. I left an inline suggestion to anchor them with ^ and $.
We should also add a test to packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart to verify this behavior and prevent regression:
test('Dart2WasmTarget.buildFiles respects compilerConfig.sourceMaps and matches modules', () {
final File wasmFile = environment.buildDir.childFile('main.dart.wasm')..createSync();
final File mjsFile = environment.buildDir.childFile('main.dart.mjs')..createSync();
final File mapFile = environment.buildDir.childFile('main.dart.wasm.map')..createSync();
final File partWasmFile = environment.buildDir.childFile('main.dart_module1.wasm')..createSync();
final File partMapFile = environment.buildDir.childFile('main.dart_module1.wasm.map')..createSync();
final targetWithMaps = Dart2WasmTarget(const WasmCompilerConfig(sourceMaps: true), const NoOpAnalytics());
expect(targetWithMaps.buildFiles(environment), containsAll(<File>[wasmFile, mjsFile, mapFile, partWasmFile, partMapFile]));
final targetWithoutMaps = Dart2WasmTarget(const WasmCompilerConfig(sourceMaps: false), const NoOpAnalytics());
expect(targetWithoutMaps.buildFiles(environment), containsAll(<File>[wasmFile, mjsFile, partWasmFile]));
expect(targetWithoutMaps.buildFiles(environment), isNot(contains(mapFile)));
expect(targetWithoutMaps.buildFiles(environment), isNot(contains(partMapFile)));
});|
CI had a failure that stopped further tests from running. We need to investigate to determine the root cause. SHA at time of execution: b4e7870. Possible causes:
A blank commit, or merging to head, will be required to resume running CI for this PR. Error Details: Stack trace: |
flutter/flutter@846664b...fc1ad95 2026-07-15 [email protected] [iOS] Migrate FlutterKeyboardInsetManager to Swift (flutter/flutter#189425) 2026-07-15 [email protected] Roll Dart SDK from 05bf153370c4 to 0c408ff6dce9 (4 revisions) (flutter/flutter#189487) 2026-07-15 [email protected] Implement UberSDF lines to replace LineContents-based AA lines (flutter/flutter#188514) 2026-07-15 [email protected] Fix stale eagerWinner reference in GestureArenaManager when rejected before arena close (flutter/flutter#187008) 2026-07-15 [email protected] Disable some Windows tests that are flaking on CI (flutter/flutter#189477) 2026-07-15 dmgr Added unified check-run user manual (flutter/flutter#189453) 2026-07-15 [email protected] Roll Skia from 88954ef8f36d to ab2410bc857c (9 revisions) (flutter/flutter#189474) 2026-07-14 [email protected] [agents] Refactor shepherd-prs skill into a pure Markdown runbook using native gh CLI (flutter/flutter#189095) 2026-07-14 [email protected] Add missing name to mirroring workflow (flutter/flutter#189439) 2026-07-14 [email protected] Add support for WASM deferred loading. (flutter/flutter#189308) 2026-07-14 [email protected] fix `templateDefaultGradleVersion` todo (flutter/flutter#189466) 2026-07-14 [email protected] Roll Fuchsia Linux SDK from oOETA0ISPouDt2xBo... to lLFbh5kFWbUGgC9Ek... (flutter/flutter#189469) 2026-07-14 [email protected] Use ServicesBinding.instance.exitApplication instead of exit(0) in multiple_windows example (flutter/flutter#189364) 2026-07-14 [email protected] Add CpuArch to the Device class (flutter/flutter#189207) 2026-07-14 [email protected] Fix space formatting in cherry-pick label for flutter_cp.dart (flutter/flutter#189463) 2026-07-14 [email protected] Roll pub packages (flutter/flutter#189454) 2026-07-14 [email protected] [flutter_tools] Format plugin example template to match dart format (flutter/flutter#188382) 2026-07-14 [email protected] Move renamed x64->ARM benchmarks out of bringup (flutter/flutter#189400) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
The dart2wasm compiler supports deferred loading now producing multiple wasm modules when deferred imports are present.
This change exposes wasm deferred loading for Flutter apps as well. It adds a few things:
--enable-wasm-deferred-loadingflag that gets plumbed through to the compiler.