Skip to content

Commit 50c020e

Browse files
authored
[browser] Preload dotnet.js (#114534)
1 parent 69329ef commit 50c020e

File tree

6 files changed

+180
-0
lines changed

6 files changed

+180
-0
lines changed

eng/testing/scenarios/BuildWasmAppsJobsList.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,4 @@ Wasm.Build.Tests.WasmTemplateTests
4646
Wasm.Build.Tests.WorkloadTests
4747
Wasm.Build.Tests.MT.Blazor.SimpleMultiThreadedTests
4848
Wasm.Build.Tests.DebugLevelTests
49+
Wasm.Build.Tests.PreloadingTests

src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ Copyright (c) .NET Foundation. All rights reserved.
209209
<_WasmBootConfigFileName Condition="'$(_WasmBootConfigFileName)' == '' and '$(_TargetingNET100OrLater)' == 'true'">dotnet.boot.js</_WasmBootConfigFileName>
210210
<_WasmBootConfigFileName Condition="'$(_WasmBootConfigFileName)' == ''">blazor.boot.json</_WasmBootConfigFileName>
211211
<_WasmPublishBootConfigFileName>publish.$(_WasmBootConfigFileName)</_WasmPublishBootConfigFileName>
212+
<_WasmPreloadAssets>$(WasmPreloadAssets)</_WasmPreloadAssets>
213+
<_WasmPreloadAssets Condition="'$(_WasmPreloadAssets)' == ''">true</_WasmPreloadAssets>
212214

213215
<!-- Workaround for https://github.com/dotnet/sdk/issues/12114-->
214216
<PublishDir Condition="'$(AppendRuntimeIdentifierToOutputPath)' != 'true' AND '$(PublishDir)' == '$(OutputPath)$(RuntimeIdentifier)\$(PublishDirName)\'">$(OutputPath)$(PublishDirName)\</PublishDir>
@@ -445,7 +447,107 @@ Copyright (c) .NET Foundation. All rights reserved.
445447
>
446448
<Output TaskParameter="Endpoints" ItemName="_WasmBuildBootConfigStaticWebAssetEndpoint" />
447449
</DefineStaticWebAssetEndpoints>
450+
</Target>
451+
452+
<PropertyGroup>
453+
<GenerateHtmlAssetPlaceholdersBuildStaticWebAssetsDependsOn>
454+
_AddWasmPreloadBuildProperties;
455+
$(GenerateHtmlAssetPlaceholdersBuildStaticWebAssetsDependsOn)
456+
</GenerateHtmlAssetPlaceholdersBuildStaticWebAssetsDependsOn>
457+
<GenerateHtmlAssetPlaceholdersPublishStaticWebAssetsDependsOn>
458+
_AddWasmPreloadPublishProperties;
459+
$(GenerateHtmlAssetPlaceholdersPublishStaticWebAssetsDependsOn)
460+
</GenerateHtmlAssetPlaceholdersPublishStaticWebAssetsDependsOn>
461+
</PropertyGroup>
462+
463+
<Target Name="_WasmConfigurePreload">
464+
<ItemGroup>
465+
<AppendPreloadRelPreloadProperty Include="Append">
466+
<UpdateTarget>Property</UpdateTarget>
467+
<Name>PreloadRel</Name>
468+
<Value>preload</Value>
469+
</AppendPreloadRelPreloadProperty>
470+
<AppendPreloadAsScriptProperty Include="Append">
471+
<UpdateTarget>Property</UpdateTarget>
472+
<Name>PreloadAs</Name>
473+
<Value>script</Value>
474+
</AppendPreloadAsScriptProperty>
475+
<AppendPreloadPriorityHighProperty Include="Append">
476+
<UpdateTarget>Property</UpdateTarget>
477+
<Name>PreloadPriority</Name>
478+
<Value>high</Value>
479+
</AppendPreloadPriorityHighProperty>
480+
<AppendPreloadCrossoriginAnonymousProperty Include="Append">
481+
<UpdateTarget>Property</UpdateTarget>
482+
<Name>PreloadCrossorigin</Name>
483+
<Value>anonymous</Value>
484+
</AppendPreloadCrossoriginAnonymousProperty>
485+
<AppendPreloadOrder1Property Include="Append">
486+
<UpdateTarget>Property</UpdateTarget>
487+
<Name>PreloadOrder</Name>
488+
<Value>1</Value>
489+
</AppendPreloadOrder1Property>
490+
<AppendGroupWebAssemblyProperty Include="Append">
491+
<UpdateTarget>Property</UpdateTarget>
492+
<Name>PreloadGroup</Name>
493+
<Value>webassembly</Value>
494+
</AppendGroupWebAssemblyProperty>
495+
496+
<!-- Label=Include matches endpoints with fingerprint; Label=Exclude matches endpoints without fingerprint -->
497+
<_WasmPreloadEndpointFilter Include="Property" Name="Label" Mode="Include" Condition="'$(_WasmFingerprintAssets)' == 'true' and ('$(StaticWebAssetProjectMode)' == 'Default' or '$(_WasmFingerprintDotnetJs)' == 'true')" />
498+
<_WasmPreloadEndpointFilter Include="Property" Name="Label" Mode="Exclude" Condition="'@(_WasmPreloadEndpointFilter)' == ''" />
499+
</ItemGroup>
500+
</Target>
501+
502+
<Target Name="_AddWasmPreloadBuildProperties" DependsOnTargets="_WasmConfigurePreload;_AddWasmStaticWebAssets" BeforeTargets="GenerateStaticWebAssetsManifest" Condition="'$(_WasmPreloadAssets)' == 'true'">
503+
<ItemGroup>
504+
<_WasmPreloadBuildScriptAsset Include="@(StaticWebAsset)" Condition="'%(AssetKind)' != 'Publish' and '%(FileName)%(Extension)' == '$(_WasmBootConfigFileName)'" />
505+
</ItemGroup>
506+
507+
<FilterStaticWebAssetEndpoints
508+
Endpoints="@(StaticWebAssetEndpoint)"
509+
Assets="@(_WasmPreloadBuildScriptAsset)"
510+
Filters="@(_WasmPreloadEndpointFilter)"
511+
>
512+
<Output TaskParameter="FilteredEndpoints" ItemName="_WasmPreloadBuildScriptAssetEndpoint" />
513+
</FilterStaticWebAssetEndpoints>
448514

515+
<UpdateStaticWebAssetEndpoints
516+
EndpointsToUpdate="@(_WasmPreloadBuildScriptAssetEndpoint)"
517+
AllEndpoints="@(_WasmPreloadBuildScriptAssetEndpoint)"
518+
Operations="@(AppendPreloadRelPreloadProperty);@(AppendPreloadAsScriptProperty);@(AppendPreloadPriorityHighProperty);@(AppendPreloadCrossoriginAnonymousProperty);@(AppendPreloadOrder1Property);@(AppendGroupWebAssemblyProperty)"
519+
>
520+
<Output TaskParameter="UpdatedEndpoints" ItemName="_UpdatedWasmPreloadBuildAssetEndpoint" />
521+
</UpdateStaticWebAssetEndpoints>
522+
<ItemGroup>
523+
<StaticWebAssetEndpoint Remove="@(_WasmPreloadBuildScriptAssetEndpoint)" />
524+
<StaticWebAssetEndpoint Include="@(_UpdatedWasmPreloadBuildAssetEndpoint)" />
525+
</ItemGroup>
526+
</Target>
527+
<Target Name="_AddWasmPreloadPublishProperties" DependsOnTargets="_WasmConfigurePreload;_AddPublishWasmBootJsonToStaticWebAssets" BeforeTargets="GenerateStaticWebAssetsPublishManifest" Condition="'$(_WasmPreloadAssets)' == 'true'">
528+
<ItemGroup>
529+
<_WasmPreloadPublishScriptAsset Include="@(StaticWebAsset)" Condition="'%(AssetKind)' != 'Build' and '%(FileName)%(Extension)' == '$(_WasmPublishBootConfigFileName)'" />
530+
</ItemGroup>
531+
532+
<FilterStaticWebAssetEndpoints
533+
Endpoints="@(StaticWebAssetEndpoint)"
534+
Assets="@(_WasmPreloadPublishScriptAsset)"
535+
Filters="@(_WasmPreloadEndpointFilter)"
536+
>
537+
<Output TaskParameter="FilteredEndpoints" ItemName="_WasmPreloadPublishScriptAssetEndpoint" />
538+
</FilterStaticWebAssetEndpoints>
539+
540+
<UpdateStaticWebAssetEndpoints
541+
EndpointsToUpdate="@(_WasmPreloadPublishScriptAssetEndpoint)"
542+
AllEndpoints="@(_WasmPreloadPublishScriptAssetEndpoint)"
543+
Operations="@(AppendPreloadRelPreloadProperty);@(AppendPreloadAsScriptProperty);@(AppendPreloadPriorityHighProperty);@(AppendPreloadCrossoriginAnonymousProperty);@(AppendPreloadOrder1Property);@(AppendGroupWebAssemblyProperty)"
544+
>
545+
<Output TaskParameter="UpdatedEndpoints" ItemName="_UpdatedWasmPreloadPublishAssetEndpoint" />
546+
</UpdateStaticWebAssetEndpoints>
547+
<ItemGroup>
548+
<StaticWebAssetEndpoint Remove="@(_WasmPreloadPublishScriptAssetEndpoint)" />
549+
<StaticWebAssetEndpoint Include="@(_UpdatedWasmPreloadPublishAssetEndpoint)" />
550+
</ItemGroup>
449551
</Target>
450552

451553
<Target Name="ProvideDefaultUserRuntimeConfig" BeforeTargets="_GenerateRuntimeConfigurationFilesInputCache" Condition="'$(GenerateRuntimeConfigurationFiles)' == 'true'">
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.IO;
5+
using System.Linq;
6+
using Xunit;
7+
using Xunit.Abstractions;
8+
9+
#nullable enable
10+
11+
namespace Wasm.Build.Tests;
12+
13+
public class PreloadingTests : WasmTemplateTestsBase
14+
{
15+
public PreloadingTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
16+
: base(output, buildContext)
17+
{
18+
}
19+
20+
[Theory]
21+
[InlineData(false, false)]
22+
[InlineData(false, true)]
23+
[InlineData(true, false)]
24+
[InlineData(true, true)]
25+
public void PreloadAssets(bool isPublish, bool fingerprintAssets)
26+
{
27+
Configuration config = Configuration.Debug;
28+
ProjectInfo info = CopyTestAsset(config, aot: false, TestAsset.WasmBasicTestApp, "PreloadAssets");
29+
30+
// TODO: AssertAppBundle doesn't with fingerprinted dotnet.js at the moment
31+
string extraMSBuildArgs = $"-p:OverrideHtmlAssetPlaceholders=true -p:WasmFingerprintAssets={fingerprintAssets}";
32+
if (isPublish)
33+
PublishProject(info, config, new PublishOptions(ExtraMSBuildArgs: extraMSBuildArgs, AssertAppBundle: false));
34+
else
35+
BuildProject(info, config, new BuildOptions(ExtraMSBuildArgs: extraMSBuildArgs, AssertAppBundle: false));
36+
37+
string? indexHtmlPath = null;
38+
if (isPublish)
39+
{
40+
indexHtmlPath = Path.Combine(
41+
GetBinFrameworkDir(config, forPublish: isPublish),
42+
"..",
43+
"index.html"
44+
);
45+
}
46+
else
47+
{
48+
string objDir = Path.Combine(GetObjDir(config), "staticwebassets", "htmlassetplaceholders", "build");
49+
indexHtmlPath = Directory.EnumerateFiles(objDir, "*.html").SingleOrDefault();
50+
}
51+
52+
Assert.True(File.Exists(indexHtmlPath));
53+
string indexHtmlContent = File.ReadAllText(indexHtmlPath);
54+
55+
if (fingerprintAssets)
56+
{
57+
// Expect to find fingerprinted preload
58+
Assert.Contains("<link href=\"_framework/dotnet", indexHtmlContent);
59+
Assert.DoesNotContain("<link href=\"_framework/dotnet.js\"", indexHtmlContent);
60+
}
61+
else
62+
{
63+
// Expect to find non-fingerprinted preload
64+
Assert.Contains("<link href=\"_framework/dotnet.js\"", indexHtmlContent);
65+
}
66+
}
67+
}

src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,12 @@ public virtual string GetBinFrameworkDir(Configuration config, bool forPublish,
626626
throw new NotImplementedException();
627627
}
628628

629+
public string GetObjDir(Configuration config, string framework, string? projectDir = null)
630+
{
631+
EnsureProjectDirIsSet();
632+
return Path.Combine(projectDir ?? ProjectDir!, "obj", config.ToString(), framework);
633+
}
634+
629635
[MemberNotNull(nameof(ProjectDir))]
630636
protected void EnsureProjectDirIsSet()
631637
{

src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ void OnErrorMessage(string msg)
376376
public string GetBinFrameworkDir(Configuration config, bool forPublish, string? framework = null, string? projectDir = null) =>
377377
_provider.GetBinFrameworkDir(config, forPublish, framework ?? DefaultTargetFramework, projectDir);
378378

379+
public string GetObjDir(Configuration config, string? framework = null, string? projectDir = null) =>
380+
_provider.GetObjDir(config, framework ?? DefaultTargetFramework, projectDir);
381+
379382
public BuildPaths GetBuildPaths(Configuration config, bool forPublish) =>
380383
_provider.GetBuildPaths(config, forPublish);
381384

src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<title>WasmLazyLoading</title>
88
<meta charset="UTF-8">
99
<meta name="viewport" content="width=device-width, initial-scale=1.0">
10+
<link rel="preload" id="webassembly" />
1011
<script type='module' src="./main.js"></script>
1112
<script type='module' src="./profiler.js"></script>
1213
</head>

0 commit comments

Comments
 (0)