[browser] Make WASM framework asset CopyToOutputDirectory configurable#127285
[browser] Make WASM framework asset CopyToOutputDirectory configurable#127285maraf wants to merge 18 commits intodotnet:mainfrom
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>
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>
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>
- Gate webcil directory assertion on UseWebcil; when disabled, assemblies
are materialized as DLLs in fx/_framework/ instead of webcil/.
- Update SatelliteAssembliesFromPackageReference to check obj/ paths
(webcil/{locale}/ or fx/{name}/_framework/{locale}/) instead of
bin/_framework/ which is no longer populated.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Update targets comment to reflect CopyToOutputDirectory=Never behavior - Use named arguments for isUsingWorkloads/isNativeBuild parameters - Remove unused nativeDirLabel variable Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore dotnet.native.wasm check in the build branch of MultiClientHostedBuildAndPublish to match the publish branch, ensuring both clients have native assets materialized independently. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…aded worker - Remove accidentally committed WasmAppHost symlink pointing to local Codespace build artifacts path - Add dotnet.native.worker.mjs validation in AssertBuildBundle for multi-threaded build scenarios to match publish-path coverage 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>
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>
…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>
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 dotnet#126407 review feedback (build-only, server statically serves client assets). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… asset copy Introduce a private MSBuild property _WasmFrameworkCopyToOutputDirectory that switches CopyToOutputDirectory between 'Never' (default) and 'PreserveNewest' for WASM framework/webcil static web assets in Microsoft.NET.Sdk.WebAssembly.Browser.targets. Enable it with 'PreserveNewest' in eng/testing/tests.browser.targets so library tests that run from bin/ without the static web assets middleware can still find the framework files. Fixes the regression from dotnet#126407 tracked in dotnet#127257. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara |
|
Replaced by a cleaner branch off main. |
There was a problem hiding this comment.
Pull request overview
This PR makes build-time copying of WASM framework/static web assets configurable (defaulting to not copying), while restoring the previous “copy to bin/” behavior for in-tree browser/library tests that run without the static web assets middleware.
Changes:
- Introduces
_WasmFrameworkCopyToOutputDirectoryin the WASM Browser SDK targets and routes framework/webcilCopyToOutputDirectorybehavior through it (defaultNever). - Sets
_WasmFrameworkCopyToOutputDirectory=PreserveNewestineng/testing/tests.browser.targetsto fix in-tree test runs that execute directly frombin/. - Updates WASM build tests to validate the new default build layout (framework assets in
obj/materialization) and adjusts helpers to locate boot config appropriately.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs | Adds helpers/assertions for build-time (non-publish) asset layout under obj/ and updates bundle assertions accordingly. |
| src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs | Extends GetFilesTable wrapper to pass an optional boot-config directory. |
| src/mono/wasm/Wasm.Build.Tests/SatelliteLoadingTests.cs | Updates satellite assembly location checks to use obj/ (webcil or materialized fx) instead of bin/_framework. |
| src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs | Adds bootConfigDir parameter to locate boot config when fingerprinting is enabled. |
| src/mono/wasm/Wasm.Build.Tests/ModuleConfigTests.cs | Adjusts symbol-map file lookup to search obj/ build locations when build-time copying is disabled. |
| src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs | Updates build-vs-publish file stat paths for the new default layout (but currently has a correctness issue—see PR comment). |
| src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs | Updates hosted build assertions to check obj/ materialized framework files and adds a runtime verification via dotnet run --no-build + Playwright fetch. |
| src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs | Adjusts resource DLL assertions to use build-time obj/ locations. |
| src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets | Adds _WasmFrameworkCopyToOutputDirectory (default Never) and uses it for relevant framework/webcil static web assets. |
| eng/testing/tests.browser.targets | Forces framework assets to copy to output for in-tree browser tests by setting _WasmFrameworkCopyToOutputDirectory=PreserveNewest (should be conditional). |
|
|
||
| <!-- Library tests run directly from bin/ without the static web assets middleware, | ||
| so copy framework files to the output directory. See https://github.com/dotnet/runtime/issues/127257. --> | ||
| <_WasmFrameworkCopyToOutputDirectory>PreserveNewest</_WasmFrameworkCopyToOutputDirectory> |
There was a problem hiding this comment.
This overrides _WasmFrameworkCopyToOutputDirectory unconditionally. To keep the file overrideable (and consistent with the surrounding properties in this PropertyGroup), consider setting it only when it’s not already set (e.g., add a Condition checking for empty).
| <_WasmFrameworkCopyToOutputDirectory>PreserveNewest</_WasmFrameworkCopyToOutputDirectory> | |
| <_WasmFrameworkCopyToOutputDirectory Condition="'$(_WasmFrameworkCopyToOutputDirectory)' == ''">PreserveNewest</_WasmFrameworkCopyToOutputDirectory> |
| BuildPaths buildObjPaths = paths with { BinFrameworkDir = fxFrameworkDir }; | ||
| IDictionary<string, (string fullPath, bool unchanged)> pathsDict = | ||
| GetFilesTable(info.ProjectName, aot, paths, unchanged: false); | ||
| GetFilesTable(info.ProjectName, aot, buildObjPaths, unchanged: false, bootConfigDir: paths.ObjDir); | ||
|
|
||
| // dotnet.native.* are produced by the native rebuild into obj/wasm/for-build/ using |
There was a problem hiding this comment.
In this test, pathsDict is repurposed later for publish output paths, but then reused again for the “second build” StatFiles(pathsDict) / CompareStat(...) checks. After the publish step, pathsDict points at publish paths, so the second-build stat/compare is no longer validating build outputs. Consider keeping separate dictionaries for build vs publish (or recomputing pathsDict/BuildPaths for the second build) before calling StatFiles/CompareStat for the build phase.
Note
This PR was created with the assistance of GitHub Copilot.
Summary
Fixes the library-tests regression from #126407 tracked in #127257.
#126407 switched the WASM framework / webcil static web asset
CopyToOutputDirectoryfromPreserveNewesttoNever, which is correct fordotnet run(static web assets middleware serves files out ofobj/fx/). But library tests in this repo run the app directly frombin/without the middleware, so the framework files are missing and loadingdotnet.*.jsfails.Changes
Microsoft.NET.Sdk.WebAssembly.Browser.targets: introduce a private MSBuild property_WasmFrameworkCopyToOutputDirectory(defaultNever) and route the threeCopyToOutputDirectoryvalues through it (Computed/webcil assets, Framework assets, and the post-UpdatePackageStaticWebAssetsitem update).eng/testing/tests.browser.targets: set_WasmFrameworkCopyToOutputDirectorytoPreserveNewestso library tests copy framework assets to the output directory as before.Default behavior for regular
dotnet run/ Blazor WASM scenarios is unchanged.