Add support for gzip compression during build and publish (#23611)

* Add support for gzip compression during build and publish

3.2 shipped with gzip compression during build and publish. During the port to 5.0, the build and publish
pipeline was different and ended up only during brotli compression during publish. However, during build
the app size is now up to 20MB. Statically compressing runtime assets during build reduces the payload size
to about 8.5 MB. This should help with faster initial boot ups and perception.

* Quarantine test

* More quarantine
This commit is contained in:
Pranav K 2020-07-03 17:20:17 -07:00 committed by GitHub
parent 8768cab874
commit 499a3bcdc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 223 additions and 10 deletions

View File

@ -319,6 +319,22 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
return filePath; return filePath;
} }
public static string DirectoryExists(MSBuildResult result, params string[] paths)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
var filePath = Path.Combine(result.Project.DirectoryPath, Path.Combine(paths));
if (!Directory.Exists(filePath))
{
throw new DirectoryMissingException(result, filePath);
}
return filePath;
}
public static void FileCountEquals(MSBuildResult result, int expected, string directoryPath, string searchPattern, SearchOption searchOption = SearchOption.AllDirectories) public static void FileCountEquals(MSBuildResult result, int expected, string directoryPath, string searchPattern, SearchOption searchOption = SearchOption.AllDirectories)
{ {
if (result == null) if (result == null)
@ -820,6 +836,19 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
protected override string Heading => $"File: '{FilePath}' was not found."; protected override string Heading => $"File: '{FilePath}' was not found.";
} }
private class DirectoryMissingException : MSBuildXunitException
{
public DirectoryMissingException(MSBuildResult result, string directoryPath)
: base(result)
{
DirectoryPath = directoryPath;
}
public string DirectoryPath { get; }
protected override string Heading => $"Directory: '{DirectoryPath}' was not found.";
}
private class FileCountException : MSBuildXunitException private class FileCountException : MSBuildXunitException
{ {
public FileCountException(MSBuildResult result, int expected, string directoryPath, string searchPattern, string[] files) public FileCountException(MSBuildResult result, int expected, string directoryPath, string searchPattern, string[] files)

View File

@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
public class WasmBuildIncrementalismTest public class WasmBuildIncrementalismTest
{ {
[Fact] [Fact]
public async Task Build_WithLinker_IsIncremental() public async Task Build_IsIncremental()
{ {
// Arrange // Arrange
using var project = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" }); using var project = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" });
@ -40,6 +40,37 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
} }
} }
[Fact]
public async Task Build_GzipCompression_IsIncremental()
{
// Arrange
using var project = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" });
var result = await MSBuildProcessManager.DotnetMSBuild(project);
Assert.BuildPassed(result);
var gzipCompressionDirectory = Path.Combine(project.IntermediateOutputDirectory, "build-gz");
Assert.DirectoryExists(result, gzipCompressionDirectory);
// Act
var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, gzipCompressionDirectory);
// Assert
for (var i = 0; i < 3; i++)
{
result = await MSBuildProcessManager.DotnetMSBuild(project);
Assert.BuildPassed(result);
var newThumbPrint = FileThumbPrint.CreateFolderThumbprint(project, gzipCompressionDirectory);
Assert.Equal(thumbPrint.Count, newThumbPrint.Count);
for (var j = 0; j < thumbPrint.Count; j++)
{
Assert.Equal(thumbPrint[j], newThumbPrint[j]);
}
}
}
[Fact] [Fact]
public async Task Build_SatelliteAssembliesFileIsPreserved() public async Task Build_SatelliteAssembliesFileIsPreserved()
{ {

View File

@ -28,10 +28,14 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "dotnet.wasm"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "dotnet.wasm");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "dotnet.wasm.gz");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", DotNetJsFileName); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", DotNetJsFileName);
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.dll"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.dll");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.dll"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.dll");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.Text.Json.dll"); // Verify dependencies are part of the output. Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.Text.Json.dll"); // Verify dependencies are part of the output.
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.Text.Json.dll.gz"); // Verify dependencies are part of the output.
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.dll");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.dll.gz");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.pdb"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.pdb");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.pdb"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.pdb");
@ -55,10 +59,14 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "dotnet.wasm"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "dotnet.wasm");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "dotnet.wasm.gz");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", DotNetJsFileName); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", DotNetJsFileName);
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.dll"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.dll");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.dll"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.dll");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.Text.Json.dll"); // Verify dependencies are part of the output. Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.Text.Json.dll"); // Verify dependencies are part of the output.
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.Text.Json.dll.gz");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.dll");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.dll.gz");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.pdb"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.pdb");
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.pdb"); Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.pdb");

View File

@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
var buildOutputDirectory = project.BuildOutputDirectory; var buildOutputDirectory = project.BuildOutputDirectory;
// Act // Act
var compressedFilesFolder = Path.Combine("..", "blazorwasm", project.IntermediateOutputDirectory, "brotli"); var compressedFilesFolder = Path.Combine("..", "blazorwasm", project.IntermediateOutputDirectory, "compress");
var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder); var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
// Assert // Assert
@ -120,7 +120,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
var buildOutputDirectory = project.BuildOutputDirectory; var buildOutputDirectory = project.BuildOutputDirectory;
// Act // Act
var compressedFilesFolder = Path.Combine("..", "blazorwasm", project.IntermediateOutputDirectory, "brotli"); var compressedFilesFolder = Path.Combine("..", "blazorwasm", project.IntermediateOutputDirectory, "compress");
var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder); var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
// Assert // Assert
@ -157,6 +157,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
var extension = Path.GetExtension(file); var extension = Path.GetExtension(file);
if (extension != ".br" && extension != ".gz") if (extension != ".br" && extension != ".gz")
{ {
Assert.FileExists(result, file + ".gz");
Assert.FileExists(result, file + ".br"); Assert.FileExists(result, file + ".br");
} }
} }

View File

@ -208,7 +208,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
// Verify compression works // Verify compression works
Assert.FileExists(result, blazorPublishDirectory, "_framework", "dotnet.wasm.br"); Assert.FileExists(result, blazorPublishDirectory, "_framework", "dotnet.wasm.br");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br"); // Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br"); //
// Verify static assets are in the publish directory // Verify static assets are in the publish directory
Assert.FileExists(result, blazorPublishDirectory, "index.html"); Assert.FileExists(result, blazorPublishDirectory, "index.html");
@ -311,6 +311,11 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.br"); Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.br");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br"); Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "dotnet.wasm.gz");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll.gz");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.gz");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.gz");
VerifyServiceWorkerFiles(result, blazorPublishDirectory, VerifyServiceWorkerFiles(result, blazorPublishDirectory,
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"), serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
serviceWorkerContent: "// This is the production service worker", serviceWorkerContent: "// This is the production service worker",
@ -352,6 +357,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
} }
[Fact] [Fact]
[QuarantinedTest]
public async Task Publish_HostedApp_WithSatelliteAssemblies() public async Task Publish_HostedApp_WithSatelliteAssemblies()
{ {
// Arrange // Arrange
@ -444,6 +450,11 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.br"); Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.br");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br"); Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "dotnet.wasm.gz");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll.gz");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.gz");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.gz");
VerifyServiceWorkerFiles(result, blazorPublishDirectory, VerifyServiceWorkerFiles(result, blazorPublishDirectory,
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"), serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
serviceWorkerContent: "// This is the production service worker", serviceWorkerContent: "// This is the production service worker",
@ -539,6 +550,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
// Regression test to verify satellite assemblies from the blazor app are copied to the published app's wwwroot output directory as // Regression test to verify satellite assemblies from the blazor app are copied to the published app's wwwroot output directory as
// part of publishing in VS // part of publishing in VS
[Fact] [Fact]
[QuarantinedTest]
public async Task Publish_HostedApp_VisualStudio_WithSatelliteAssemblies() public async Task Publish_HostedApp_VisualStudio_WithSatelliteAssemblies()
{ {
// Simulates publishing the same way VS does by setting BuildProjectReferences=false. // Simulates publishing the same way VS does by setting BuildProjectReferences=false.
@ -643,6 +655,11 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.br"); Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.br");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br"); Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "dotnet.wasm.gz");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll.gz");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.gz");
Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.gz");
VerifyServiceWorkerFiles(result, blazorPublishDirectory, VerifyServiceWorkerFiles(result, blazorPublishDirectory,
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"), serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
serviceWorkerContent: "// This is the production service worker", serviceWorkerContent: "// This is the production service worker",

View File

@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Razor.Tasks
var input = FilesToCompress[i]; var input = FilesToCompress[i];
var inputFullPath = input.GetMetadata("FullPath"); var inputFullPath = input.GetMetadata("FullPath");
var relativePath = input.GetMetadata("RelativePath"); var relativePath = input.GetMetadata("RelativePath");
var outputRelativePath = Path.Combine(OutputDirectory, CalculateTargetPath(relativePath)); var outputRelativePath = Path.Combine(OutputDirectory, CalculateTargetPath(relativePath, ".br"));
var outputItem = new TaskItem(outputRelativePath); var outputItem = new TaskItem(outputRelativePath);
input.CopyMetadataTo(outputItem); input.CopyMetadataTo(outputItem);
@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Razor.Tasks
return builder.ToString(); return builder.ToString();
} }
private static string CalculateTargetPath(string relativePath) internal static string CalculateTargetPath(string relativePath, string extension)
{ {
// RelativePath can be long and if used as-is to write the output, might result in long path issues on Windows. // RelativePath can be long and if used as-is to write the output, might result in long path issues on Windows.
// Instead we'll calculate a fixed length path by hashing the input file name. This uses SHA1 similar to the Hash task in MSBuild // Instead we'll calculate a fixed length path by hashing the input file name. This uses SHA1 similar to the Hash task in MSBuild
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Razor.Tasks
builder.Append(InvalidPathChars.Contains(c) ? '+' : c); builder.Append(InvalidPathChars.Contains(c) ? '+' : c);
} }
builder.Append(".br"); builder.Append(extension);
return builder.ToString(); return builder.ToString();
} }
} }

View File

@ -0,0 +1,70 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.Razor.Tasks
{
public class GZipCompress : Task
{
[Required]
public ITaskItem[] FilesToCompress { get; set; }
[Output]
public ITaskItem[] CompressedFiles { get; set; }
[Required]
public string OutputDirectory { get; set; }
public override bool Execute()
{
CompressedFiles = new ITaskItem[FilesToCompress.Length];
Directory.CreateDirectory(OutputDirectory);
System.Threading.Tasks.Parallel.For(0, FilesToCompress.Length, i =>
{
var file = FilesToCompress[i];
var inputPath = file.ItemSpec;
var relativePath = file.GetMetadata("RelativePath");
var outputRelativePath = Path.Combine(
OutputDirectory,
BrotliCompress.CalculateTargetPath(relativePath, ".gz"));
var outputItem = new TaskItem(outputRelativePath);
outputItem.SetMetadata("RelativePath", relativePath + ".gz");
CompressedFiles[i] = outputItem;
if (File.Exists(outputRelativePath) && File.GetLastWriteTimeUtc(inputPath) < File.GetLastWriteTimeUtc(outputRelativePath))
{
// Incrementalism. If input source doesn't exist or it exists and is not newer than the expected output, do nothing.
Log.LogMessage(MessageImportance.Low, $"Skipping '{inputPath}' because '{outputRelativePath}' is newer than '{inputPath}'.");
return;
}
try
{
using var sourceStream = File.OpenRead(inputPath);
using var fileStream = File.Create(outputRelativePath);
using var stream = new GZipStream(fileStream, CompressionLevel.Optimal);
sourceStream.CopyTo(stream);
}
catch (Exception e)
{
Log.LogErrorFromException(e);
return;
}
});
return !Log.HasLoggedErrors;
}
}
}

View File

@ -15,6 +15,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.BlazorWriteSatelliteAssemblyFile" AssemblyFile="$(RazorSdkBuildTasksAssembly)" /> <UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.BlazorWriteSatelliteAssemblyFile" AssemblyFile="$(RazorSdkBuildTasksAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.BlazorReadSatelliteAssemblyFile" AssemblyFile="$(RazorSdkBuildTasksAssembly)" /> <UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.BlazorReadSatelliteAssemblyFile" AssemblyFile="$(RazorSdkBuildTasksAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.BrotliCompress" AssemblyFile="$(RazorSdkBuildTasksAssembly)" /> <UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.BrotliCompress" AssemblyFile="$(RazorSdkBuildTasksAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.GzipCompress" AssemblyFile="$(RazorSdkBuildTasksAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.CreateBlazorTrimmerRootDescriptorFile" AssemblyFile="$(RazorSdkBuildTasksAssembly)" /> <UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.CreateBlazorTrimmerRootDescriptorFile" AssemblyFile="$(RazorSdkBuildTasksAssembly)" />
<PropertyGroup> <PropertyGroup>
@ -151,6 +152,30 @@ Copyright (c) .NET Foundation. All rights reserved.
</Target> </Target>
<Target Name="_ProcessBlazorWasmOutputs" DependsOnTargets="_ResolveBlazorWasmOutputs"> <Target Name="_ProcessBlazorWasmOutputs" DependsOnTargets="_ResolveBlazorWasmOutputs">
<PropertyGroup>
<_BlazorBuildGZipCompressDirectory>$(IntermediateOutputPath)build-gz\</_BlazorBuildGZipCompressDirectory>
</PropertyGroup>
<!--
Compress referenced binaries using GZip during build. This skips files such as the project's assemblies
that change from build to build. Runtime assets contribute to the bulk of the download size. Compressing it
has the most benefit while avoiding any ongoing costs to the dev inner loop.
-->
<ItemGroup>
<_GzipFileToCompressForBuild
Include="@(ReferenceCopyLocalPaths)"
RelativePath="$(_BlazorOutputPath)%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(FileName)%(Extension)"
Condition="'%(Extension)' == '.dll' or '%(ReferenceCopyLocalPaths.AssetType)' == 'native'" />
</ItemGroup>
<GZipCompress
FilesToCompress="@(_GzipFileToCompressForBuild)"
OutputDirectory="$(_BlazorBuildGZipCompressDirectory)">
<Output TaskParameter="CompressedFiles" ItemName="_BlazorBuildGZipCompressedFile" />
<Output TaskParameter="CompressedFiles" ItemName="FileWrites" />
</GZipCompress>
<ItemGroup> <ItemGroup>
<_BlazorWriteSatelliteAssembly Include="@(_BlazorOutputWithTargetPath->HasMetadata('Culture'))" /> <_BlazorWriteSatelliteAssembly Include="@(_BlazorOutputWithTargetPath->HasMetadata('Culture'))" />
@ -238,6 +263,15 @@ Copyright (c) .NET Foundation. All rights reserved.
<CopyToPublishDirectory>Never</CopyToPublishDirectory> <CopyToPublishDirectory>Never</CopyToPublishDirectory>
</_BlazorWebAssemblyStaticWebAsset> </_BlazorWebAssemblyStaticWebAsset>
<_BlazorWebAssemblyStaticWebAsset Include="@(_BlazorBuildGZipCompressedFile)">
<SourceId>$(PackageId)</SourceId>
<SourceType></SourceType>
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
<BasePath>$(StaticWebAssetBasePath)</BasePath>
<RelativePath>$([System.String]::Copy('%(_BlazorBuildGZipCompressedFile.RelativePath)').Replace('\','/').Substring(8))</RelativePath>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</_BlazorWebAssemblyStaticWebAsset>
<StaticWebAsset Include="@(_BlazorWebAssemblyStaticWebAsset)" /> <StaticWebAsset Include="@(_BlazorWebAssemblyStaticWebAsset)" />
<_ExternalStaticWebAsset Include="@(_BlazorWebAssemblyStaticWebAsset)" SourceType="Generated" /> <_ExternalStaticWebAsset Include="@(_BlazorWebAssemblyStaticWebAsset)" SourceType="Generated" />
</ItemGroup> </ItemGroup>
@ -305,6 +339,20 @@ Copyright (c) .NET Foundation. All rights reserved.
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/> <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
</Copy> </Copy>
<Copy
SourceFiles="@(_BlazorBuildGZipCompressedFile)"
DestinationFiles="@(_BlazorBuildGZipCompressedFile->'$(OutDir)%(RelativePath)')"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
ErrorIfLinkFails="$(ErrorIfLinkFailsForCopyFilesToOutputDirectory)">
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
</Copy>
</Target> </Target>
<Target Name="_BlazorWasmPrepareForLink" BeforeTargets="PrepareForILLink"> <Target Name="_BlazorWasmPrepareForLink" BeforeTargets="PrepareForILLink">
@ -411,12 +459,12 @@ Copyright (c) .NET Foundation. All rights reserved.
<Target Name="_BlazorCompressPublishFiles" AfterTargets="_ProcessPublishFilesForBlazor" Condition="'$(BlazorEnableCompression)' != 'false'"> <Target Name="_BlazorCompressPublishFiles" AfterTargets="_ProcessPublishFilesForBlazor" Condition="'$(BlazorEnableCompression)' != 'false'">
<PropertyGroup> <PropertyGroup>
<_CompressedFileOutputPath>$(IntermediateOutputPath)brotli\</_CompressedFileOutputPath> <_CompressedFileOutputPath>$(IntermediateOutputPath)compress\</_CompressedFileOutputPath>
<_BlazorWebAssemblyBrotliIncremental>true</_BlazorWebAssemblyBrotliIncremental> <_BlazorWebAssemblyBrotliIncremental>true</_BlazorWebAssemblyBrotliIncremental>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<_BrotliFileToCompress <_FileToCompress
Include="@(ResolvedFileToPublish)" Include="@(ResolvedFileToPublish)"
Condition="$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').StartsWith('wwwroot/'))" /> Condition="$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').StartsWith('wwwroot/'))" />
</ItemGroup> </ItemGroup>
@ -427,7 +475,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<BrotliCompress <BrotliCompress
OutputDirectory="$(_CompressedFileOutputPath)" OutputDirectory="$(_CompressedFileOutputPath)"
FilesToCompress="@(_BrotliFileToCompress)" FilesToCompress="@(_FileToCompress)"
CompressionLevel="$(_BlazorBrotliCompressionLevel)" CompressionLevel="$(_BlazorBrotliCompressionLevel)"
SkipIfOutputIsNewer="$(_BlazorWebAssemblyBrotliIncremental)" SkipIfOutputIsNewer="$(_BlazorWebAssemblyBrotliIncremental)"
ToolAssembly="$(_RazorSdkToolAssembly)"> ToolAssembly="$(_RazorSdkToolAssembly)">
@ -436,8 +484,17 @@ Copyright (c) .NET Foundation. All rights reserved.
<Output TaskParameter="CompressedFiles" ItemName="FileWrites" /> <Output TaskParameter="CompressedFiles" ItemName="FileWrites" />
</BrotliCompress> </BrotliCompress>
<GZipCompress
OutputDirectory="$(_CompressedFileOutputPath)"
FilesToCompress="@(_FileToCompress)">
<Output TaskParameter="CompressedFiles" ItemName="_BlazorPublishGZipCompressedFile" />
<Output TaskParameter="CompressedFiles" ItemName="FileWrites" />
</GZipCompress>
<ItemGroup> <ItemGroup>
<ResolvedFileToPublish Include="@(_BrotliCompressedFile)" /> <ResolvedFileToPublish Include="@(_BrotliCompressedFile)" />
<ResolvedFileToPublish Include="@(_BlazorPublishGZipCompressedFile)" />
</ItemGroup> </ItemGroup>
</Target> </Target>