Uh oh!
There was an error while loading. Please reload this page.
[browser] Don't copy framework assets to output during build - #126407
Conversation
During build, the WebAssembly SDK was copying all .wasm and .js framework assets to bin/wwwroot/_framework/ via CopyToOutputDirectory=PreserveNewest. This is unnecessary because dotnet run uses the static web assets middleware, which serves files directly from their obj/ locations using the manifest. Change CopyToOutputDirectory from PreserveNewest to Never for: - Webcil-converted assets (Computed static web assets) - Materialized framework assets (dotnet.js, dotnet.native.wasm, etc.) This eliminates ~178 file copies during build while preserving correct behavior for dotnet run (static web assets middleware) and publish (CopyToPublishDirectory was already Never). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
With CopyToOutputDirectory=Never, framework assets are no longer copied to bin/wwwroot/_framework/ during build. They are served from obj/ locations via the static web assets middleware during dotnet run. Only assert bundle file layout for publish, where files are still physically copied to the output. Build-time tests that run the app (via dotnet run or xharness) still validate the app works correctly - they just don't check for files in bin/ that are intentionally no longer there. The Blazor-specific AssertBundle already had this guard WasmTemplateTestsBase path needed updating. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
With CopyToOutputDirectory=Never, framework files are no longer copied to bin/_framework/ during build. Update MultiClientHostedBuildAndPublish to assert framework files exist in obj/<config>/<tfm>/fx/<ProjectName>/ _framework/ for build, matching the materialization path used by UpdatePackageStaticWebAssets. Publish assertions remain unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Revert the IsPublish guard that skipped AssertWasmSdkBundle for builds.
Instead, add AssertBuildBundle that validates framework files are in their
correct obj/ subdirectories with CopyToOutputDirectory=Never:
- dotnet.js (boot config) in obj/{config}/{tfm}/
- dotnet.runtime.js, maps, ICU in obj/{config}/{tfm}/fx/{name}/_framework/
- dotnet.native.* in fx/_framework/ (non-native) or wasm/for-build/ (native)
- webcil assemblies in obj/{config}/{tfm}/webcil/
- framework files NOT in bin/_framework/
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>With framework assets no longer copied to bin/_framework/ during build,
update the three remaining failing tests to look for files in the obj
subdirectories where they actually live:
- Blazor BuildPublishTests.DefaultTemplate_WithResources_Publish:
probe satellite assemblies under obj/{config}/{tfm}/webcil/{locale}/
(webcil) or obj/{config}/{tfm}/fx/{name}/_framework/{locale}/ (non-webcil)
for the build-time assertion.
- BuildPublishTests.BuildThenPublishWithAOT: stat framework files for the
first build from obj/{config}/{tfm}/fx/{name}/_framework/ (JS, source
maps) and obj/{config}/{tfm}/wasm/for-build/ (native outputs). Boot
config is read from obj/{config}/{tfm}/dotnet.js via a new optional
bootConfigDir parameter on GetFilesTable used by fingerprint resolution.
- ModuleConfigTests.SymbolMapFileEmitted(isPublish=false): search for
dotnet.native*.js.symbols in obj/wasm/for-build/ (native rebuild) and
in obj/fx/*/_framework/ as a fallback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
🤖 Copilot Code Review — PR #126407Note This review was AI/Copilot-generated. Models used: Claude Opus 4.6 (primary), Claude Sonnet 4.5. Holistic AssessmentMotivation: The PR addresses a genuine build performance issue — ~178 unnecessary file copies during build. The static web assets middleware already serves files from obj/ locations via the manifest, making the Approach: The approach is clean and minimal — 3 attribute value changes in production code ( Summary: Detailed Findings✅ Production Change — Correct and well-scopedThe three changes in
The updated XML comments (lines 430–435) accurately describe the new behavior. ✅ New |
Addresses review feedback: centralizes the obj/.../fx/<source-id>/_framework/ discovery logic in WasmSdkBasedProjectProvider.GetMaterializedFrameworkDir and uses it from AssertBuildBundle, BuildPublishTests and Blazor/MiscTests so the per-project fx subdir name is discovered instead of hardcoded. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Apply GetMaterializedFrameworkDir helper to the remaining three locations flagged by the review bot: Blazor/BuildPublishTests GetBuildSatelliteBaseDir, SatelliteLoadingTests, and ModuleConfigTests (the last still inlines the extra 'wasm/for-build' search path but deduplicates the fx-base Path.Combine). - Explain why dotnet.native.worker.mjs is not compared against the runtime pack in AssertBuildBundle (parity with AssertBundle's publish path comment). - Log when AssertWasmSdkBundle skips AssertBuildBundle because NonDefaultFrameworkDir is set, so the coverage gap is visible in test output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
maraf
commented
Apr 17, 2026
Note Comment authored with assistance from GitHub Copilot. Thanks for the thorough pass. Addressing the findings in 00635ac + c6fe5e5: ✅ Code duplication (5× ✅ ✅ Duplicate ✅ Left as-is:
|
…n obj/fx
With CopyToOutputDirectory=Never, the materialized framework dir under
obj/{config}/{tfm}/fx/{source-id}/_framework/ contains dotnet.runtime.js
under its canonical (non-fingerprinted) name during build. Fingerprinting
is applied later when publishing to bin. GetFilesTable rewrites the entry
from the boot config (which already reflects the publish layout), yielding
a fingerprinted path that does not exist in obj/fx and causes CompareStat
to report the file as missing.
Override the dotnet.runtime.js entry to the unfingerprinted obj/fx path
for the build-phase stat, mirroring the existing native-file override.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>maraf
commented
Apr 21, 2026
@javiercn Do we have scenario that would still rely on the actual files in the bin folder? |
Run the server via 'dotnet run --no-build' and use Playwright's APIRequestContext to verify that each referenced client's framework files are served from the obj/ materialized directory at the /<client>/_framework/* base path. This guards the hosted scenario from PR #126407 review feedback (build-only, server statically serves client assets). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
maraf
commented
Apr 21, 2026
Note This comment was generated with the assistance of GitHub Copilot. CI analysis for the latest push (build 1388930):
The single failure is This is the well-known Helix Docker-pull infrastructure flake tracked in #117164 — tests never started; the failing test ( |
Note
This PR was created with the assistance of GitHub Copilot.
Summary
During build, the WebAssembly SDK copies all
.wasmand.jsframework assets (~178 files) tobin/wwwroot/_framework/viaCopyToOutputDirectory=PreserveNewest. This is unnecessary becausedotnet runuses the static web assets middleware, which serves files directly from theirobj/locations via the manifest (staticwebassets.runtime.json).Changes
Set
CopyToOutputDirectory=Never(wasPreserveNewest) for threeDefineStaticWebAssets/ item-update calls inMicrosoft.NET.Sdk.WebAssembly.Browser.targets:.wasmfiles produced from.dlldotnet.js,dotnet.native.wasm, runtime JS, etc.UpdatePackageStaticWebAssets) — the per-project copies inobj/fx/Validation
dotnet buildwithTargetOS=browser)dotnet runstarts WasmAppHost dev server correctly42)bin/wwwroot/_framework/drops from ~178 files to 2 (only hot-reload module + dotnet.js from a separate code path)CopyToPublishDirectorywas alreadyNever— publish is unaffectedNotes
PreserveNewestwas added for Blazor WASM hosted scenarios where a server project serves the client's framework files. This scenario needs separate validation.obj/dirs), so physical copies inbin/are not needed fordotnet run.Downstream impact: dotnet/sdk BlazorWasm test baselines
The
Microsoft.NET.Sdk.BlazorWebAssembly.TestsStaticWebAssetsBaselines/*.Build.*.jsonfiles in dotnet/sdk currently assert that framework assets live under${ProjectPath}\bin\Debug\${Tfm}\wwwroot\_framework\after Build. Across the Build baselines there are ~1,940bin\Debugreferences covering ~481 framework files:dotnet.*runtime/loader JS +.wasm+.map(+.gz) — 12 filesicudt_*.dat.gz— 3 filesblazor.webassembly.js(+.gz) — 2 files.wasmassemblies (+.gzcopies).resources.wasmsatellitesOnce this change flows to dotnet/sdk, these baselines will need to be regenerated so framework assets point at their intermediate/
RestorePathlocations instead ofbin\. App-project outputs (blazorwasm.wasm/.pdb) and project references (RazorClassLibrary.*) are unaffected and remain underbin\.