Skip to content

Commit 26dff42

Browse files
authored
Write import map to html files (#46233)
1 parent 2ee3787 commit 26dff42

File tree

9 files changed

+506
-4
lines changed

9 files changed

+506
-4
lines changed

src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,15 @@ Copyright (c) .NET Foundation. All rights reserved.
5050
<DebuggerSupport Condition="'$(DebuggerSupport)' == '' and '$(Configuration)' != 'Debug'">false</DebuggerSupport>
5151
<BlazorCacheBootResources Condition="'$(BlazorCacheBootResources)' == ''">true</BlazorCacheBootResources>
5252

53+
<_TargetingNETBefore80>$([MSBuild]::VersionLessThan('$(TargetFrameworkVersion)', '8.0'))</_TargetingNETBefore80>
5354
<_TargetingNET80OrLater>$([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '8.0'))</_TargetingNET80OrLater>
54-
<WasmFingerprintDotnetJs>true</WasmFingerprintDotnetJs>
55-
<WasmFingerprintDotnetJs Condition="'$(_TargetingNET80OrLater)' == 'true'">false</WasmFingerprintDotnetJs>
55+
<_TargetingNETBefore100>$([MSBuild]::VersionLessThan('$(TargetFrameworkVersion)', '10.0'))</_TargetingNETBefore100>
56+
57+
<!-- 8 < .NET we want to fingerprint dotnet.js because it's part of the blazor.boot.json which is loaded from blazor.webassembly.js -->
58+
<!-- 8 <= .NET < 10 we don't want to fingerprint dotnet.js because it's path is hardcoded in blazor.webassembly.js -->
59+
<!-- 10 <= .NET we want to leave fingerprinting to WasmSDK because it knows if import maps where applied -->
60+
<WasmFingerprintDotnetJs Condition="'$(_TargetingNETBefore80)' == 'true'">true</WasmFingerprintDotnetJs>
61+
<WasmFingerprintDotnetJs Condition="'$(_TargetingNET80OrLater)' == 'true' and '$(_TargetingNETBefore100)' == 'true'">false</WasmFingerprintDotnetJs>
5662
<WasmEnableWebcil Condition="'$(WasmEnableWebcil)' == '' and ('$(TargetFrameworkIdentifier)' != '.NETCoreApp' or '$(_TargetingNET80OrLater)' != 'true')">false</WasmEnableWebcil>
5763

5864
<!-- Turn off parts of the build that do not apply to Blazor projects -->
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
<!--
2+
***********************************************************************************************
3+
Microsoft.NET.Sdk.StaticWebAssets.HtmlImportMap.targets
4+
5+
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
6+
created a backup copy. Incorrect changes to this file will make it
7+
impossible to load or build your projects from the command-line or the IDE.
8+
9+
Copyright (c) .NET Foundation. All rights reserved.
10+
***********************************************************************************************
11+
-->
12+
13+
<Project ToolsVersion="14.0">
14+
15+
<UsingTask TaskName="Microsoft.AspNetCore.StaticWebAssets.Tasks.WriteImportMapToHtml" AssemblyFile="$(StaticWebAssetsSdkBuildTasksAssembly)" />
16+
17+
<PropertyGroup>
18+
19+
<!--
20+
ResolveBuildRelatedStaticWebAssets
21+
ResolveHtmlImportMapBuildStaticWebAssets
22+
GenerateHtmlImportMapBuildStaticWebAssets
23+
ResolveHtmlImportMapBuildConfiguration
24+
-->
25+
<ResolveBuildRelatedStaticWebAssetsDependsOn>
26+
$(ResolveBuildRelatedStaticWebAssetsDependsOn);
27+
ResolveHtmlImportMapBuildStaticWebAssets;
28+
</ResolveBuildRelatedStaticWebAssetsDependsOn>
29+
<ResolveCompressedFilesDependsOn>
30+
$(ResolveCompressedFilesDependsOn);
31+
ResolveHtmlImportMapBuildStaticWebAssets
32+
</ResolveCompressedFilesDependsOn>
33+
<ResolveBuildServiceWorkerStaticWebAssetsDependsOn>
34+
$(ResolveBuildServiceWorkerStaticWebAssetsDependsOn);
35+
ResolveHtmlImportMapBuildStaticWebAssets
36+
</ResolveBuildServiceWorkerStaticWebAssetsDependsOn>
37+
<ResolveHtmlImportMapBuildStaticWebAssetsDependsOn>
38+
GenerateHtmlImportMapBuildStaticWebAssets;
39+
$(ResolveHtmlImportMapBuildStaticWebAssetsDependsOn)
40+
</ResolveHtmlImportMapBuildStaticWebAssetsDependsOn>
41+
<GenerateHtmlImportMapBuildStaticWebAssetsDependsOn>
42+
ResolveHtmlImportMapBuildConfiguration;
43+
$(GenerateHtmlImportMapBuildStaticWebAssetsDependsOn)
44+
</GenerateHtmlImportMapBuildStaticWebAssetsDependsOn>
45+
46+
<!--
47+
ResolvePublishRelatedStaticWebAssets
48+
ResolveHtmlImportMapPublishStaticWebAssets
49+
GenerateHtmlImportMapPublishStaticWebAssets
50+
ResolveHtmlImportMapPublishConfiguration
51+
-->
52+
<ResolvePublishRelatedStaticWebAssetsDependsOn>
53+
$(ResolvePublishRelatedStaticWebAssetsDependsOn);
54+
ResolveHtmlImportMapPublishStaticWebAssets
55+
</ResolvePublishRelatedStaticWebAssetsDependsOn>
56+
<ResolvePublishCompressedStaticWebAssetsDependsOn>
57+
$(ResolvePublishCompressedStaticWebAssetsDependsOn);
58+
ResolveHtmlImportMapPublishStaticWebAssets
59+
</ResolvePublishCompressedStaticWebAssetsDependsOn>
60+
<ResolvePublishServiceWorkerStaticWebAssetsDependsOn>
61+
$(ResolvePublishServiceWorkerStaticWebAssetsDependsOn);
62+
ResolveHtmlImportMapPublishStaticWebAssets
63+
</ResolvePublishServiceWorkerStaticWebAssetsDependsOn>
64+
<ResolveHtmlImportMapPublishStaticWebAssetsDependsOn>
65+
GenerateHtmlImportMapPublishStaticWebAssets;
66+
$(ResolveHtmlImportMapPublishStaticWebAssetsDependsOn)
67+
</ResolveHtmlImportMapPublishStaticWebAssetsDependsOn>
68+
<GenerateHtmlImportMapPublishStaticWebAssetsDependsOn>
69+
ResolveHtmlImportMapPublishConfiguration;
70+
$(GenerateHtmlImportMapPublishStaticWebAssetsDependsOn)
71+
</GenerateHtmlImportMapPublishStaticWebAssetsDependsOn>
72+
73+
</PropertyGroup>
74+
75+
<!-- Build -->
76+
77+
<Target Name="ResolveHtmlImportMapBuildConfiguration">
78+
<PropertyGroup>
79+
<_BuildImportMapHtmlPath>$([MSBuild]::NormalizeDirectory($(_StaticWebAssetsIntermediateOutputPath), 'importmaphtml', 'build'))</_BuildImportMapHtmlPath>
80+
</PropertyGroup>
81+
82+
<MakeDir Directories="$(_BuildImportMapHtmlPath)"/>
83+
84+
<ItemGroup>
85+
<_HtmlStaticWebAssets Include="@(StaticWebAsset)" Condition="'%(AssetKind)' != 'Publish' and '%(Extension)' == '.html'" />
86+
<_EsModuleCandidate Include="@(StaticWebAsset)" Condition="'%(AssetKind)' != 'Publish'" />
87+
</ItemGroup>
88+
89+
<FilterStaticWebAssetEndpoints Condition="'@(_EsModuleCandidate)' != ''"
90+
Endpoints="@(StaticWebAssetEndpoint)"
91+
Assets="@(_EsModuleCandidate)"
92+
Filters=""
93+
>
94+
<Output TaskParameter="FilteredEndpoints" ItemName="_EsModuleCandidateEndpoints" />
95+
</FilterStaticWebAssetEndpoints>
96+
</Target>
97+
98+
<Target Name="GenerateHtmlImportMapBuildStaticWebAssets" DependsOnTargets="$(GenerateHtmlImportMapBuildStaticWebAssetsDependsOn)">
99+
<WriteImportMapToHtml
100+
Endpoints="@(_EsModuleCandidateEndpoints)"
101+
HtmlFiles="@(_HtmlStaticWebAssets)"
102+
OutputPath="$(_BuildImportMapHtmlPath)">
103+
<Output TaskParameter="HtmlCandidates" ItemName="_HtmlCandidates" />
104+
<Output TaskParameter="HtmlFilesToRemove" ItemName="_HtmlFilesToRemove" />
105+
<Output TaskParameter="FileWrites" ItemName="FileWrites" />
106+
</WriteImportMapToHtml>
107+
</Target>
108+
109+
<Target Name="ResolveHtmlImportMapBuildStaticWebAssets" DependsOnTargets="$(ResolveHtmlImportMapBuildStaticWebAssetsDependsOn)">
110+
<ItemGroup>
111+
<_HtmlCandidatesNoMetadata
112+
Include="@(_HtmlCandidates)"
113+
RemoveMetadata="SourceType;AssetKind;Integrity;Fingerprint" />
114+
<_HtmlCandidatesNoMetadata ContentRoot="$(_BuildImportMapHtmlPath)" />
115+
</ItemGroup>
116+
<DefineStaticWebAssets CandidateAssets="@(_HtmlCandidatesNoMetadata)"
117+
SourceType="Computed"
118+
AssetKind="Build"
119+
>
120+
<Output TaskParameter="Assets" ItemName="_UpdatedHtmlStaticWebAssets" />
121+
</DefineStaticWebAssets>
122+
<DefineStaticWebAssetEndpoints
123+
CandidateAssets="@(_UpdatedHtmlStaticWebAssets)"
124+
ExistingEndpoints="@(StaticWebAssetEndpoint)"
125+
ContentTypeMappings="@(StaticWebAssetContentTypeMapping)"
126+
>
127+
<Output TaskParameter="Endpoints" ItemName="_UpdatedHtmlStaticWebAssetsEndpoint" />
128+
</DefineStaticWebAssetEndpoints>
129+
<FilterStaticWebAssetEndpoints Condition="'@(_HtmlFilesToRemove)' != ''"
130+
Endpoints="@(StaticWebAssetEndpoint)"
131+
Assets="@(_HtmlFilesToRemove)"
132+
Filters=""
133+
>
134+
<Output TaskParameter="FilteredEndpoints" ItemName="_HtmlFileEndpointsToRemove" />
135+
</FilterStaticWebAssetEndpoints>
136+
<ItemGroup>
137+
<StaticWebAsset Remove="@(_HtmlFilesToRemove)" />
138+
<StaticWebAsset Include="@(_UpdatedHtmlStaticWebAssets)" />
139+
<StaticWebAssetEndpoint Remove="@(_HtmlFileEndpointsToRemove)" />
140+
<StaticWebAssetEndpoint Include="@(_UpdatedHtmlStaticWebAssetsEndpoint)" />
141+
</ItemGroup>
142+
</Target>
143+
144+
<!-- Publish -->
145+
146+
<Target Name="ResolveHtmlImportMapPublishConfiguration">
147+
<PropertyGroup>
148+
<_PublishImportMapHtmlPath>$([MSBuild]::NormalizeDirectory($(_StaticWebAssetsIntermediateOutputPath), 'importmaphtml', 'publish'))</_PublishImportMapHtmlPath>
149+
</PropertyGroup>
150+
151+
<MakeDir Directories="$(_PublishImportMapHtmlPath)"/>
152+
153+
<ItemGroup>
154+
<_EsModuleCandidateForPublish Include="@(StaticWebAsset)" Condition="'%(AssetKind)' != 'Build'" />
155+
</ItemGroup>
156+
157+
<FilterStaticWebAssetEndpoints Condition="'@(_EsModuleCandidateForPublish)' != ''"
158+
Endpoints="@(StaticWebAssetEndpoint)"
159+
Assets="@(_EsModuleCandidateForPublish)"
160+
Filters=""
161+
>
162+
<Output TaskParameter="FilteredEndpoints" ItemName="_EsModuleCandidateForPublishEndpoints" />
163+
</FilterStaticWebAssetEndpoints>
164+
</Target>
165+
166+
<Target Name="GenerateHtmlImportMapPublishStaticWebAssets" DependsOnTargets="$(GenerateHtmlImportMapPublishStaticWebAssetsDependsOn)">
167+
<WriteImportMapToHtml
168+
Endpoints="@(_EsModuleCandidateForPublishEndpoints)"
169+
HtmlFiles="@(_HtmlStaticWebAssets)"
170+
OutputPath="$(_PublishImportMapHtmlPath)">
171+
<Output TaskParameter="HtmlCandidates" ItemName="_HtmlPublishCandidates" />
172+
<Output TaskParameter="HtmlFilesToRemove" ItemName="_HtmlPublishFilesToRemove" />
173+
<Output TaskParameter="FileWrites" ItemName="FileWrites" />
174+
</WriteImportMapToHtml>
175+
</Target>
176+
177+
<Target Name="ResolveHtmlImportMapPublishStaticWebAssets" DependsOnTargets="$(ResolveHtmlImportMapPublishStaticWebAssetsDependsOn)">
178+
<ItemGroup>
179+
<_HtmlPublishCandidatesNoMetadata
180+
Include="@(_HtmlPublishCandidates)"
181+
RemoveMetadata="SourceType;AssetKind;Integrity;Fingerprint" />
182+
<_HtmlPublishCandidatesNoMetadata ContentRoot="$(_PublishImportMapHtmlPath)" />
183+
</ItemGroup>
184+
<DefineStaticWebAssets CandidateAssets="@(_HtmlPublishCandidatesNoMetadata)"
185+
SourceType="Computed"
186+
AssetKind="Publish"
187+
>
188+
<Output TaskParameter="Assets" ItemName="_UpdatedHtmlPublishStaticWebAssets" />
189+
</DefineStaticWebAssets>
190+
<DefineStaticWebAssetEndpoints
191+
CandidateAssets="@(_UpdatedHtmlPublishStaticWebAssets)"
192+
ExistingEndpoints="@(StaticWebAssetEndpoint)"
193+
ContentTypeMappings="@(StaticWebAssetContentTypeMapping)"
194+
>
195+
<Output TaskParameter="Endpoints" ItemName="_UpdatedHtmlPublishStaticWebAssetsEndpoint" />
196+
</DefineStaticWebAssetEndpoints>
197+
<FilterStaticWebAssetEndpoints Condition="'@(_HtmlPublishFilesToRemove)' != ''"
198+
Endpoints="@(StaticWebAssetEndpoint)"
199+
Assets="@(_HtmlPublishFilesToRemove)"
200+
Filters=""
201+
>
202+
<Output TaskParameter="FilteredEndpoints" ItemName="_HtmlPublishFileEndpointsToRemove" />
203+
</FilterStaticWebAssetEndpoints>
204+
<ItemGroup>
205+
<StaticWebAsset Remove="@(_HtmlPublishFilesToRemove)" />
206+
<StaticWebAsset Include="@(_UpdatedHtmlPublishStaticWebAssets)" />
207+
<StaticWebAssetEndpoint Remove="@(_HtmlPublishFileEndpointsToRemove)" />
208+
<StaticWebAssetEndpoint Include="@(_UpdatedHtmlPublishStaticWebAssetsEndpoint)" />
209+
</ItemGroup>
210+
</Target>
211+
212+
</Project>

src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,5 +737,7 @@ Copyright (c) .NET Foundation. All rights reserved.
737737
<Import Project="Microsoft.NET.Sdk.StaticWebAssets.Compression.targets" Condition="'$(CompressionEnabled)' == 'true'" />
738738

739739
<Import Project="Microsoft.NET.Sdk.StaticWebAssets.ServiceWorker.targets" Condition="'$(ServiceWorkerAssetsManifest)' != ''" />
740+
741+
<Import Project="Microsoft.NET.Sdk.StaticWebAssets.HtmlImportMap.targets" Condition="'$(WriteImportMapToHtml)' == 'true'" />
740742

741743
</Project>

src/StaticWebAssetsSdk/Tasks/Utils/ArtifactWriter.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@ namespace Microsoft.AspNetCore.StaticWebAssets.Tasks.Utils;
1010

1111
public static class ArtifactWriter
1212
{
13-
public static void PersistFileIfChanged<T>(this Task task, T manifest, string artifactPath, JsonTypeInfo<T> serializer)
13+
public static bool PersistFileIfChanged<T>(this Task task, T manifest, string artifactPath, JsonTypeInfo<T> serializer)
1414
{
1515
var data = JsonSerializer.SerializeToUtf8Bytes(manifest, serializer);
16+
return PersistFileIfChanged(task, data, artifactPath);
17+
}
18+
19+
public static bool PersistFileIfChanged(this Task task, byte[] data, string artifactPath)
20+
{
1621
var newHash = ComputeHash(data);
1722
var fileExists = File.Exists(artifactPath);
1823
var existingManifestHash = fileExists ? ComputeHash(artifactPath) : null;
@@ -21,15 +26,18 @@ public static void PersistFileIfChanged<T>(this Task task, T manifest, string ar
2126
{
2227
task.Log.LogMessage(MessageImportance.Low, $"Creating artifact because artifact file '{artifactPath}' does not exist.");
2328
File.WriteAllBytes(artifactPath, data);
29+
return true;
2430
}
2531
else if (!string.Equals(newHash, existingManifestHash, StringComparison.Ordinal))
2632
{
2733
task.Log.LogMessage(MessageImportance.Low, $"Updating artifact because artifact version '{newHash}' is different from existing artifact hash '{existingManifestHash}'.");
2834
File.WriteAllBytes(artifactPath, data);
35+
return true;
2936
}
3037
else
3138
{
3239
task.Log.LogMessage(MessageImportance.Low, $"Skipping artifact updated because artifact version '{existingManifestHash}' has not changed.");
40+
return false;
3341
}
3442
}
3543

0 commit comments

Comments
 (0)