Skip to content

Instantly share code, notes, and snippets.

@SQL-MisterMagoo
Last active May 18, 2023 22:50
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SQL-MisterMagoo/8ee43276c7ad1de06866ebf4a02c4c8e to your computer and use it in GitHub Desktop.
Save SQL-MisterMagoo/8ee43276c7ad1de06866ebf4a02c4c8e to your computer and use it in GitHub Desktop.
Compress Static Files in wwwroot (or anywhere) in Blazor WebAssembly

Compress Static Files in Blazor WebAssembly Hosted

This goes into your msbuild config (normally csproj) and runs before the Publish Task, before files are copied to the final destination.

<!-- 2022 @SQL-MisterMagoo containing some code from (c) .NET Foundation. All rights reserved. -->

<PropertyGroup Condition="'$(_BlazorWebAssemblySdkToolAssembly)'==''">
  <_SDKRoot>$(NetCoreRoot)sdk\$(NETCoreSDKVersion)\Sdks</_SDKRoot>
  <BlazorWebAssemblySdkDirectoryRoot>$(_SDKRoot)\Microsoft.NET.Sdk.BlazorWebAssembly\</BlazorWebAssemblySdkDirectoryRoot>
  <_BlazorWebAssemblySdkTasksAssembly Condition="'$(_BlazorWebAssemblySdkTasksAssembly)'==''">$(BlazorWebAssemblySdkDirectoryRoot)tools\net472\Microsoft.NET.Sdk.BlazorWebAssembly.Tasks.dll</_BlazorWebAssemblySdkTasksAssembly>
  <_BlazorWebAssemblySdkToolAssembly Condition="'$(_BlazorWebAssemblySdkToolAssembly)'==''">$(BlazorWebAssemblySdkDirectoryRoot)tools\$(TargetFramework)\Microsoft.NET.Sdk.BlazorWebAssembly.Tool.dll</_BlazorWebAssemblySdkToolAssembly>
</PropertyGroup>


<!-- The next two lines are Copyright (c) .NET Foundation. All rights reserved. -->
<UsingTask TaskName="Microsoft.NET.Sdk.BlazorWebAssembly.BrotliCompress" AssemblyFile="$(_BlazorWebAssemblySdkTasksAssembly)"/>
<UsingTask TaskName="Microsoft.NET.Sdk.BlazorWebAssembly.GzipCompress" AssemblyFile="$(_BlazorWebAssemblySdkTasksAssembly)"/>

<Target Name="CustomGZipAndBrotliCompression" BeforeTargets="Publish">

	<!-- ************* THIS IS WHERE YOU CHOOSE WHAT TO COMPRESS *****************
		you probably don't want to change anything else - just this ItemGroup 
	-->
	<ItemGroup>
		<MyStaticFiles Include="$(PublishDir)\\wwwroot\\**\\*.css"/>
		<MyStaticFiles Include="$(PublishDir)\\wwwroot\\**\\*.js"/>
	</ItemGroup>

	<!-- Call the BlazorWebAssembly Task GZipCompress and store the results in MyCompressedFiles -->
	<GZipCompress FilesToCompress="@(MyStaticFiles)" OutputDirectory="$(IntermediateOutputPath)compress\">
		<Output TaskParameter="CompressedFiles" ItemName="MyCompressedFiles" />
	</GZipCompress>

	<!-- Call the BlazorWebAssembly Task BrotliCompress and store the results in MyCompressedFiles -->
	<BrotliCompress OutputDirectory="$(IntermediateOutputPath)compress\" FilesToCompress="@(MyStaticFiles)" ToolAssembly="$(_BlazorWebAssemblySdkToolAssembly)" ToolExe="$(_RazorSdkDotNetHostFileName)" ToolPath="$(_RazorSdkDotNetHostDirectory)">
		<Output TaskParameter="CompressedFiles" ItemName="MyCompressedFiles" />
	</BrotliCompress>

	<!-- Log out what we have done -->
	<Message Importance="High" Text="======= Brotli/GZip Compression For @(MyCompressedFiles-&gt;Count()) Static Files =======" />
	<Message Importance="High" Text=" Compressed: %(MyCompressedFiles.OriginalItemSpec)%(MyCompressedFiles.Extension)" />
	
	<!-- Rename/move the compressed files back to to the correct place/names as they have "hashed" names at this stage. -->
	<Move SourceFiles="%(MyCompressedFiles.FullPath)" DestinationFiles="%(MyCompressedFiles.OriginalItemSpec)%(MyCompressedFiles.Extension)" />

</Target>

^-- Add whatever files you like to MyStaticFiles... Make sure not to include existing .br and .gz files, and anything in __framework !

The Target Name can be whatever you like. The BrotliCompress and GZipCompress Tasks are part of the Blazor WebAssembly SDK. This sample compresses all files in MyStaticFilesand returns MyCompressedFiles, which the Move Task uses to rename the compressed files. (BrotliCompress gives them hashed names for some reason) The compressed files are written to the PublishDir just before they are copied to the final PublishUrl - ready to be served.

You might want to change the Blazor startup on the client to make best use of the compressed files:

https://docs.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-6.0#compression

Thanks @IvanJosipovic for the link.

Compress Static Files in Blazor WebAssembly

This goes into your msbuild config (normally csproj) and runs after the Publish Task, but before files are copied to the final destination.

<Target Name="CustomGZipAndBrotliCompression" AfterTargets="Publish">

	<ItemGroup>
		<MyStaticFiles Include="$(PublishDir)\\wwwroot\\**\\*.*" />
		<MyStaticFiles Remove="$(PublishDir)\\wwwroot\\_framework\\**\\*.*" />
		<MyStaticFiles Remove="$(PublishDir)\\wwwroot\\**\\*.br" />
		<MyStaticFiles Remove="$(PublishDir)\\wwwroot\\**\\*.gz" />
	</ItemGroup>
		
	<GZipCompress
		FilesToCompress="@(MyStaticFiles)"
		OutputDirectory="$(_BlazorBuildGZipCompressDirectory)">

		<Output TaskParameter="CompressedFiles" ItemName="MyCompressedFiles" />
	</GZipCompress>
		
	<BrotliCompress 
		OutputDirectory="$(_BlazorBuildGZipCompressDirectory)" 
		FilesToCompress="@(MyStaticFiles)" 
		ToolAssembly="$(_BlazorWebAssemblySdkToolAssembly)" 
		ToolExe="$(_RazorSdkDotNetHostFileName)" 
		ToolPath="$(_RazorSdkDotNetHostDirectory)">
		<Output TaskParameter="CompressedFiles" ItemName="MyCompressedFiles" />
	</BrotliCompress>
		
	<Message Importance="High" Text="======= Brotli/GZip Compression For @(MyCompressedFiles-&gt;Count()) Static Files =======" />
	<Message Importance="High" Text=" Compressing: %(MyCompressedFiles.OriginalItemSpec)%(MyCompressedFiles.Extension)" />
	<Move SourceFiles="%(MyCompressedFiles.FullPath)" DestinationFiles="%(MyCompressedFiles.OriginalItemSpec)%(MyCompressedFiles.Extension)" />
</Target>

^-- Add whatever files you like to MyStaticFiles... Make sure to exclude existing .br and .gz files, and anything in __framework !

The Target Name can be whatever you like. The BrotliCompress and GZipCompress Tasks are part of the Blazor WebAssembly SDK. This sample compresses all files in MyStaticFilesand returns MyCompressedFiles, which the Move Task uses to rename the compressed files. (BrotliCompress gives them hashed names for some reason) The compressed files are written to the PublishDir just before they are copied to the final PublishUrl - ready to be served.

You might want to change the Blazor startup on the client to make best use of the compressed files:

https://docs.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-6.0#compression

Thanks @IvanJosipovic for the link.

@simonziegler
Copy link

Looking forward to giving this a run around the block.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment