Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2512418
disable wasmhotreload if not explicitly set and bundlerfriendlybootco…
ArcadeMode Mar 4, 2026
3b65b19
casing
ArcadeMode Mar 4, 2026
2f96dcb
add build test no hotreload in bootjson
ArcadeMode Mar 6, 2026
34fa937
Merge branch 'main' into wasm-no-hotreload-with-bundlerfriendlybootco…
ArcadeMode Mar 6, 2026
f809af2
aot is not relevant here
ArcadeMode Mar 6, 2026
43d8563
pass explicitly no build props
ArcadeMode Mar 6, 2026
862aeb3
disable compression, hotreload and fingerprinting when bundlerfriendly
ArcadeMode Mar 10, 2026
d01a074
update test to work
ArcadeMode Mar 10, 2026
23435bc
allow pdbs as file in rollup
ArcadeMode Mar 10, 2026
ffef895
Merge branch 'main' into wasm-no-hotreload-with-bundlerfriendlybootco…
ArcadeMode Mar 10, 2026
db997e1
more appropriate test location
ArcadeMode Mar 10, 2026
9d455f8
unused import
ArcadeMode Mar 10, 2026
dc1b9ec
Merge branch 'main' into wasm-no-hotreload-with-bundlerfriendlybootco…
ArcadeMode Mar 10, 2026
558f778
spelling/grammar
ArcadeMode Mar 10, 2026
f2764ef
Apply suggestions from code review
ArcadeMode Mar 10, 2026
18c7d4f
dont change targets order
ArcadeMode Mar 11, 2026
a6c0da2
allow enabling compression
ArcadeMode Mar 11, 2026
dab4b6b
target the underscore property
ArcadeMode Mar 11, 2026
ba4e664
dont include content, update staticwebassets to get copied to outdir
ArcadeMode Mar 11, 2026
247615c
change order, ensure fingerprint and compression remain disabled
ArcadeMode Mar 11, 2026
1c1f5b5
bundler friendly builds treat assets as they are during publish
ArcadeMode Mar 12, 2026
ba717c2
refactor private field + public method
ArcadeMode Mar 12, 2026
0ce730c
add update attribute
ArcadeMode Mar 12, 2026
4d63607
Merge branch 'main' into wasm-no-hotreload-with-bundlerfriendlybootco…
ArcadeMode Mar 12, 2026
faf2368
fix bad condition causing unwanted fingerprint disabling
ArcadeMode Mar 13, 2026
ecd01f0
only run test when building bundler-friendly
ArcadeMode Mar 13, 2026
badc32e
Merge branch 'main' into wasm-no-hotreload-with-bundlerfriendlybootco…
ArcadeMode Mar 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Copyright (c) .NET Foundation. All rights reserved.

<!-- Compression -->
<CompressionIncludePatterns>$(CompressionIncludePatterns);_framework\**</CompressionIncludePatterns>
<CompressionIncludePatterns Condition="'$(WasmBundlerFriendlyBootConfig)' == 'true'"></CompressionIncludePatterns>
<DisableBuildCompression Condition="'$(WasmBuildingForNestedPublish)' == 'true'">true</DisableBuildCompression>
</PropertyGroup>

Expand All @@ -85,6 +86,8 @@ Copyright (c) .NET Foundation. All rights reserved.
<EnableDefaultWasmAssembliesToBundle>false</EnableDefaultWasmAssembliesToBundle>
<WasmNestedPublishAppDependsOn>_GatherWasmFilesToPublish;$(WasmNestedPublishAppDependsOn)</WasmNestedPublishAppDependsOn>
<_WasmNestedPublishAppPreTarget>ComputeFilesToPublish</_WasmNestedPublishAppPreTarget>

<_WasmEnableHotReload Condition="'$(WasmBundlerFriendlyBootConfig)' == 'true'">false</_WasmEnableHotReload>
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -210,10 +213,12 @@ Copyright (c) .NET Foundation. All rights reserved.
<_WasmInlineBootConfig Condition="'$(_WasmInlineBootConfig)' == ''">false</_WasmInlineBootConfig>
<!-- true = wasm assets will have hard fingerprint; false = wasm assets won't have even soft fingerprint -->
<_WasmFingerprintAssets>$(WasmFingerprintAssets)</_WasmFingerprintAssets>
<_WasmFingerprintAssets Condition="'$(WasmBundlerFriendlyBootConfig)' == 'true'">false</_WasmFingerprintAssets>
<_WasmFingerprintAssets Condition="'$(_WasmFingerprintAssets)' == '' and '$(_TargetingNET90OrLater)' == 'true'">true</_WasmFingerprintAssets>
<_WasmFingerprintAssets Condition="'$(_WasmFingerprintAssets)' == ''">false</_WasmFingerprintAssets>
<!-- true = dotnet.js will have hard fingerprint; false = dotnet.js will have soft fingerprint -->
<_WasmFingerprintDotnetJs>$(WasmFingerprintDotnetJs)</_WasmFingerprintDotnetJs>
<_WasmFingerprintDotnetJs Condition="'$(WasmBundlerFriendlyBootConfig)' == 'true'">false</_WasmFingerprintDotnetJs>
<_WasmFingerprintDotnetJs Condition="'$(_WasmFingerprintDotnetJs)' == ''">$(OverrideHtmlAssetPlaceholders)</_WasmFingerprintDotnetJs>
<_WasmFingerprintDotnetJs Condition="'$(_WasmFingerprintDotnetJs)' == ''">false</_WasmFingerprintDotnetJs>
<_WasmBootConfigFileName>$(WasmBootConfigFileName)</_WasmBootConfigFileName>
Expand Down Expand Up @@ -661,6 +666,43 @@ Copyright (c) .NET Foundation. All rights reserved.
</PropertyGroup>
</Target>

<Target Name="EnsureProjectAssetsInOutputDirectoryForBundlerFriendlyBuild"
BeforeTargets="ResolveBuildStaticWebAssets"
Condition="'$(WasmBundlerFriendlyBootConfig)' == 'true' and '$(IsPublishing)' != 'true'">
<!-- Fix non-publishing scenarios by copying project assets the way they are copied during publish,
so bundler-friendly builds are complete for the js bundler -->
<ItemGroup>
<StaticWebAsset Update="@(StaticWebAsset)" Condition="'%(StaticWebAsset.CopyToPublishDirectory)' != 'Never' and '%(StaticWebAsset.CopyToPublishDirectory)' != ''">
<CopyToOutputDirectory>%(StaticWebAsset.CopyToPublishDirectory)</CopyToOutputDirectory>
</StaticWebAsset>
</ItemGroup>
</Target>

<Target Name="EnsurePublishAssetsInOutputDirectoryForBundlerFriendlyBuild"
AfterTargets="_SplitStaticWebAssetsByCopyOptions"
BeforeTargets="_BuildCopyStaticWebAssetsPreserveNewest;_BuildCopyStaticWebAssetsAlways;_BuildCopyStaticWebAssetsIfDifferent"
Condition="'$(WasmBundlerFriendlyBootConfig)' == 'true' and '$(IsPublishing)' != 'true'">
Comment on lines +681 to +684
<!-- Fix non-publishing scenarios by manually adding the publish static web assets to the build static web assets
so bundler-friendly builds are complete for the js bundler -->
<ComputeStaticWebAssetsForCurrentProject
Assets="@(StaticWebAsset)"
ProjectMode="$(StaticWebAssetProjectMode)"
AssetKind="Publish"
Source="$(PackageId)">
<Output TaskParameter="StaticWebAssets" ItemName="_StaticWebAssetsToCopy" />
</ComputeStaticWebAssetsForCurrentProject>

<ComputeStaticWebAssetsTargetPaths Assets="@(_StaticWebAssetsToCopy)" PathPrefix="$(OutputPath)\wwwroot\">
<Output TaskParameter="AssetsWithTargetPath" ItemName="_StaticWebAssetsToCopyTargetPath" />
</ComputeStaticWebAssetsTargetPaths>

<ItemGroup>
<_BuildStaticWebAssetsCopyAlways Include="@(_StaticWebAssetsToCopyTargetPath)" Condition="'%(CopyToOutputDirectory)' == 'Always'" />
<_BuildStaticWebAssetsPreserveNewest Include="@(_StaticWebAssetsToCopyTargetPath)" Condition="'%(CopyToOutputDirectory)' == 'PreserveNewest'" />
<_BuildStaticWebAssetsIfDifferent Include="@(_StaticWebAssetsToCopyTargetPath)" Condition="'%(CopyToOutputDirectory)' == 'IfDifferent'" />
</ItemGroup>
</Target>

<!-- Publish starts here -->

<!-- Make sure that ResolveAssemblyReferences runs early enough to ensure satellite assemblies are populated in the ResolvedFilesToPublish -->
Expand Down
1 change: 1 addition & 0 deletions src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public abstract class BuildTestBase : IClassFixture<SharedBuildPerTestClassFixtu
public static bool IsMonoRuntime => s_buildEnv.IsMonoRuntime;
public static bool IsCoreClrRuntime => s_buildEnv.IsCoreClrRuntime;
public static bool UseWebcil => s_buildEnv.UseWebcil;
public static bool UseJavascriptBundler => EnvironmentVariables.UseJavascriptBundler;
public static string GetNuGetConfigPath()
=> Path.Combine(BuildEnvironment.TestDataPath, "nuget.config");

Expand Down
13 changes: 13 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/DebugLevelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,17 @@ public async Task PublishWithDefaultLevelAndPdbs(Configuration configuration)
RunResult result = await RunForPublishWithWebServer(options);
AssertDebugLevel(result.TestOutput, -1);
}

[ConditionalFact(typeof(BuildTestBase), nameof(UseJavascriptBundler)), TestCategory("bundler-friendly")]
public void BundlerFriendlyBuildProvidesValidOutputForNpmBuild()
{
Configuration config = Configuration.Debug;
ProjectInfo info = CopyTestAsset(config, aot: false, TestAsset.WasmBasicTestApp, "DebugLevelTests_BundlerFriendlyBootConfigHasNoHotReloadLibraryInitializer");
// Project exists and contains <WasmBundlerFriendlyBootConfig>true</WasmBundlerFriendlyBootConfig>.
BuildProject(info, config, noDefaultOptions: true, wasmFingerprintDotnetJs: false);
string bootConfigPath = GetBootConfigPath(GetBinFrameworkDir(config, forPublish: false));
string bootJSObject = ProjectProviderBase.GetBootJsonContent(bootConfigPath);
// The bundler-friendly boot config is emitted as a JavaScript object literal, not JSON, so it cannot be parsed as JSON. It can still be inspected to ensure it does not contain hot reload.
Assert.DoesNotContain("Microsoft.DotNet.HotReload.WebAssembly.Browser", bootJSObject);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Playwright;
using Xunit.Abstractions;
using Xunit;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace Wasm.Build.Tests;

public class WasmTemplateTestsBase : BuildTestBase
{
private readonly WasmSdkBasedProjectProvider _provider;
private readonly string _extraBuildArgsBuild = "-p:WasmEnableHotReload=false";
private readonly string _extraBuildArgsPublish = "-p:CompressionEnabled=false -p:WasmEnableHotReload=false";
private readonly WasmSdkBasedProjectProvider _provider;
protected readonly PublishOptions _defaultPublishOptions;
protected readonly BuildOptions _defaultBuildOptions;
protected const string DefaultRuntimeAssetsRelativePath = "./_framework/";
Expand Down Expand Up @@ -119,8 +119,6 @@ protected ProjectInfo CopyTestAsset(
extraProperties +=
"""
<WasmBundlerFriendlyBootConfig>true</WasmBundlerFriendlyBootConfig>
<WasmFingerprintAssets>false</WasmFingerprintAssets>
<CompressionEnabled>false</CompressionEnabled>
""";
}

Expand Down Expand Up @@ -190,9 +188,10 @@ public virtual (string projectDir, string buildOutput) PublishProject(
public virtual (string projectDir, string buildOutput) BuildProject(
ProjectInfo info,
Configuration configuration,
bool noDefaultOptions = false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to omit default options?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because by default it sets WasmEnableHotReload=false, this is to demonstrate it works without that as default option.

bool? isNativeBuild = null,
bool? wasmFingerprintDotnetJs = null) => // null for unset properties
BuildProjectCore(info, configuration, _defaultBuildOptions, isNativeBuild, wasmFingerprintDotnetJs);
BuildProjectCore(info, configuration, noDefaultOptions ? new BuildOptions() : _defaultBuildOptions, isNativeBuild, wasmFingerprintDotnetJs);

public virtual (string projectDir, string buildOutput) BuildProject(
ProjectInfo info,
Expand Down Expand Up @@ -242,9 +241,9 @@ public virtual (string projectDir, string buildOutput) BuildProject(
return (_projectDir, res.Output);
}

if (EnvironmentVariables.UseJavascriptBundler && buildOptions.IsPublish)
if (EnvironmentVariables.UseJavascriptBundler)
{
string publicWwwrootDir = Path.GetFullPath(Path.Combine(GetBinFrameworkDir(configuration, forPublish: true), ".."));
string publicWwwrootDir = Path.GetFullPath(Path.Combine(GetBinFrameworkDir(configuration, forPublish: buildOptions.IsPublish), ".."));
File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "JavascriptBundlers", "package.json"), Path.Combine(publicWwwrootDir, "package.json"));
File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "JavascriptBundlers", "rollup.config.mjs"), Path.Combine(publicWwwrootDir, "rollup.config.mjs"));

Expand Down Expand Up @@ -485,6 +484,9 @@ void OnErrorMessage(string msg)
}
}

public string GetBootConfigPath(string binFrameworkDir, string? bootConfigFileName = null) =>
_provider.GetBootConfigPath(binFrameworkDir, bootConfigFileName);

public string GetBinFrameworkDir(Configuration config, bool forPublish, string? framework = null, string? projectDir = null) =>
_provider.GetBinFrameworkDir(config, forPublish, framework ?? DefaultTargetFramework, projectDir);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default {
plugins: [
files({
output: 'public',
extensions: /\.(wasm|dat)$/,
extensions: /\.(wasm|dat|pdb)$/,
hash: true,
}),
files({
Expand All @@ -39,4 +39,4 @@ export default {
'process.env.NODE_ENV': '"production"'
}),
]
}
}
Loading