diff --git a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets
index f632de9957f9..16716864ec7b 100644
--- a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets
+++ b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets
@@ -49,6 +49,7 @@ Copyright (c) .NET Foundation. All rights reserved.
false
false
true
+ true
<_TargetingNETBefore80>$([MSBuild]::VersionLessThan('$(TargetFrameworkVersion)', '8.0'))
<_TargetingNET80OrLater>$([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '8.0'))
@@ -83,6 +84,15 @@ Copyright (c) .NET Foundation. All rights reserved.
GenerateBuildBlazorBootExtensionJson;
+
+ $(ResolvePublishRelatedStaticWebAssetsDependsOn);
+ _ReplaceFingerprintedBlazorJsForPublish
+
+
+ $(ResolveCompressedFilesForPublishDependsOn);
+ _ReplaceFingerprintedBlazorJsForPublish
+
+
$(GeneratePublishWasmBootJsonDependsOn);
GeneratePublishBlazorBootExtensionJson;
@@ -104,6 +114,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<_BlazorJsFile>
_framework/%(Filename)%(Extension)
+ <_BlazorJSFingerprintPattern Include="Js" Pattern="*.js" Expression="#[.{fingerprint}]!" />
+
+
+ <_BlazorJSStaticWebAsset Include="@(StaticWebAsset)" Condition="'%(FileName)' == '%(_BlazorJSFile.FileName)'" />
+ <_BlazorJSPublishCandidate Include="%(_BlazorJSStaticWebAsset.RelativeDir)%(_BlazorJSStaticWebAsset.FileName).%(_BlazorJSStaticWebAsset.Fingerprint)%(_BlazorJSStaticWebAsset.Extension)" />
+ <_BlazorJSPublishCandidate>
+ _framework/$([System.IO.Path]::GetFileNameWithoutExtension('%(Filename)'))%(Extension)
+
+
+
+
+
+
+
+
+
+
+ <_BlazorJSStaticWebAssetFullPath>@(_BlazorJSStaticWebAsset->'%(FullPath)')
+
+
+ <_BlazorJSStaticWebAsset Include="@(StaticWebAsset)" Condition="'%(AssetTraitName)' == 'Content-Encoding' and '%(RelatedAsset)' == '$(_BlazorJSStaticWebAssetFullPath)'" />
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsFingerprintingTest.cs b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsFingerprintingTest.cs
index 10e90ba8d34b..85612bd71224 100644
--- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsFingerprintingTest.cs
+++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsFingerprintingTest.cs
@@ -46,17 +46,18 @@ public void Build_FingerprintsContent_WhenEnabled()
AssertBuildAssets(manifest1, outputPath, intermediateOutputPath);
}
- public static TheoryData WriteImportMapToHtmlData => new TheoryData
+ public static TheoryData WriteImportMapToHtmlData => new TheoryData
{
- { "VanillaWasm", true },
- { "BlazorWasmMinimal", false }
+ { "VanillaWasm", "main.js", null },
+ { "BlazorWasmMinimal", "_framework/blazor.webassembly.js", "_framework/blazor.webassembly#[.{fingerprint}].js" }
};
[Theory]
[MemberData(nameof(WriteImportMapToHtmlData))]
- public void Build_WriteImportMapToHtml(string testAsset, bool assetMainJs)
+ public void Build_WriteImportMapToHtml(string testAsset, string scriptPath, string scriptPathWithFingerprintPattern)
{
ProjectDirectory = CreateAspNetSdkTestAsset(testAsset);
+ ReplaceStringInIndexHtml(ProjectDirectory, scriptPath, scriptPathWithFingerprintPattern);
var build = CreateBuildCommand(ProjectDirectory);
ExecuteCommand(build, "-p:WriteImportMapToHtml=true").Should().Pass();
@@ -65,14 +66,15 @@ public void Build_WriteImportMapToHtml(string testAsset, bool assetMainJs)
var indexHtmlPath = Directory.EnumerateFiles(Path.Combine(intermediateOutputPath, "staticwebassets", "importmaphtml", "build"), "*.html").Single();
var endpointsManifestPath = Path.Combine(intermediateOutputPath, $"staticwebassets.build.endpoints.json");
- AssertImportMapInHtml(indexHtmlPath, endpointsManifestPath, assetMainJs);
+ AssertImportMapInHtml(indexHtmlPath, endpointsManifestPath, scriptPath);
}
[Theory]
[MemberData(nameof(WriteImportMapToHtmlData))]
- public void Publish_WriteImportMapToHtml(string testAsset, bool assetMainJs)
+ public void Publish_WriteImportMapToHtml(string testAsset, string scriptPath, string scriptPathWithFingerprintPattern)
{
ProjectDirectory = CreateAspNetSdkTestAsset(testAsset);
+ ReplaceStringInIndexHtml(ProjectDirectory, scriptPath, scriptPathWithFingerprintPattern);
var projectName = Path.GetFileNameWithoutExtension(Directory.EnumerateFiles(ProjectDirectory.TestRoot, "*.csproj").Single());
@@ -80,29 +82,40 @@ public void Publish_WriteImportMapToHtml(string testAsset, bool assetMainJs)
ExecuteCommand(publish, "-p:WriteImportMapToHtml=true").Should().Pass();
var outputPath = publish.GetOutputDirectory(DefaultTfm, "Debug").ToString();
- var indexHtmlPath = Path.Combine(outputPath, "wwwroot", "index.html");
+ var indexHtmlOutputPath = Path.Combine(outputPath, "wwwroot", "index.html");
var endpointsManifestPath = Path.Combine(outputPath, $"{projectName}.staticwebassets.endpoints.json");
- AssertImportMapInHtml(indexHtmlPath, endpointsManifestPath, assetMainJs);
+ AssertImportMapInHtml(indexHtmlOutputPath, endpointsManifestPath, scriptPath);
}
- private void AssertImportMapInHtml(string indexHtmlPath, string endpointsManifestPath, bool assetMainJs)
+ private void ReplaceStringInIndexHtml(TestAsset testAsset, string scriptPath, string scriptPathWithFingerprintPattern)
+ {
+ if (scriptPathWithFingerprintPattern != null)
+ {
+ var indexHtmlPath = Path.Combine(testAsset.TestRoot, "wwwroot", "index.html");
+ var indexHtmlContent = File.ReadAllText(indexHtmlPath);
+ var newIndexHtmlContent = indexHtmlContent.Replace(scriptPath, scriptPathWithFingerprintPattern);
+ if (indexHtmlContent == newIndexHtmlContent)
+ throw new Exception($"Script replacement '{scriptPath}' for '{scriptPathWithFingerprintPattern}' didn't produce any change in '{indexHtmlPath}'");
+
+ File.WriteAllText(indexHtmlPath, newIndexHtmlContent);
+ }
+ }
+
+ private void AssertImportMapInHtml(string indexHtmlPath, string endpointsManifestPath, string scriptPath)
{
var indexHtmlContent = File.ReadAllText(indexHtmlPath);
var endpoints = JsonSerializer.Deserialize(File.ReadAllText(endpointsManifestPath));
- if (assetMainJs)
- {
- var mainJs = GetFingerprintedPath("main.js");
- Assert.DoesNotContain("src=\"main.js\"", indexHtmlContent);
- Assert.Contains($"src=\"{mainJs}\"", indexHtmlContent);
- }
+ var fingerprintedScriptPath = GetFingerprintedPath(scriptPath);
+ Assert.DoesNotContain($"src=\"{scriptPath}\"", indexHtmlContent);
+ Assert.Contains($"src=\"{fingerprintedScriptPath}\"", indexHtmlContent);
Assert.Contains(GetFingerprintedPath("_framework/dotnet.js"), indexHtmlContent);
Assert.Contains(GetFingerprintedPath("_framework/dotnet.native.js"), indexHtmlContent);
Assert.Contains(GetFingerprintedPath("_framework/dotnet.runtime.js"), indexHtmlContent);
string GetFingerprintedPath(string route)
- => endpoints.Endpoints.FirstOrDefault(e => e.Route == route && e.Selectors.Length == 0)?.AssetFile ?? throw new Exception($"Missing endpoint for file '{route}'");
+ => endpoints.Endpoints.FirstOrDefault(e => e.Route == route && e.Selectors.Length == 0)?.AssetFile ?? throw new Exception($"Missing endpoint for file '{route}' in '{endpointsManifestPath}'");
}
}