- Home
- .NET tutorials
- Static asset file sizes can be reduced by over 80% in .NET 9
Static asset file sizes can be reduced by over 80% in .NET 9
Published: Thursday 19 December 2024
The static asset delivery optimisation feature in .NET 9 uses Brotli and Gzip compression to help reduce static web asset file sizes by over 80%!
This is ideal for users on a slower network like a mobile as the response time will be significantly reduced.
Compression before .NET 9
Before .NET 9, you enabled static web assets by including this line in Program.cs
:
// Program.cs
app.UseStaticFiles();
To add compression, you can add response compression and choose either Brotli compression, Gzip compression, or both.
C# coding challenges
You could also configure what level of compression you wanted. The levels include:
- Optimal
- Fastest
- No compression
- Smallest size
Here's how you would configure it in Program.cs
:
// Program.cs
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
});
builder.Services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.SmallestSize;
});
builder.Services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.SmallestSize;
});
var app = builder.Build();
app.UseResponseCompression();
When requesting the /lib/bootstrap/dist/js/bootstrap.js
file that comes with the ASP.NET Core MVC template in .NET 8, the response sizes comes in at 144.91 kb. Compression happens when specifying the Accept-Encoding
header as part of the request. If we set the value to br
which stands for Brotli, the response size comes in at 23.08 kb. That's an 84.1% reduction in file size.
The problem with this method though is that compression happens on every request. That's a lot of overhead on a file that barely changes.
Introducing static asset delivery optimisation
But .NET 9 has resolved this by adding static asset delivery optimisation.
This adds separate compressed files to your static web assets when the project is compiled.
In most instances, you can just replace the app.UseStaticFiles
method with the app.MapStaticAssets
method in Program.cs
.
// Program.cs
app.MapStaticAssets();
Gzip compressed files are added at build time with the addition of Brotli compressed files when the project is published.
It also uses content-based etags meaning the cache is only updated when the content changes.
Compression when the project is compiled
When the project is built, the compressed .gz
files are stored in obj/Debug/net{version}/compressed
.
If you publish the project, files in the wwwroot
folder will have separate compressed .br
and .gz
files.
Depending on what is added in the Accept-Encoding
request header depends on which file is returned in the response. If br
is added, it will return the Brotli compressed file. If gzip
is added, it will return the Gzip compressed file. If both the br
and gzip
values are added, it will typically favour the Brotli compressed file. If you don't include the Accept-Encoding
request header, it will serve the full size file.
When requesting the /lib/bootstrap/dist/js/bootstrap.js
file that comes with the ASP.NET Core MVC template in .NET 9, the response size comes in at 142.28 kb. If we use Gzip compression, it comes in at 29.27 kb. And it reduces it further if we use Brotli compression at 24.01 kb. That's an 83.2% reduction on file size.
Drawbacks with static asset delivery optimisation
There are some drawbacks with using static asset delivery optimisiation.
It only works in the wwwroot
folder so if you use another folder for your static web assets, your files won't be compressed. In this scenario, you'll have to continue with using UseStaticFiles
in Program.cs
.
This is how you would set it up if you wanted your static web assets in the MyAssets
folder:
// Program.cs
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider($"{Directory.GetCurrentDirectory()}/MyAssets")
});
You would also have to add a new ItemGroup
tag to your csproj
file to ensure that these assets were always copied to the output directory.
<ItemGroup>
<Content Include="MyAssets\**\*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
It would be good if we could use static asset delivery optimisation in another folder. But there is a third-party tool we can use to do just that.
Introducing DotNetCompress
DotNetCompress allows you to compress files using the Brotli and Gzip compression. To install it, you need to run this line in a terminal:
dotnet tool install --global DotNetCompress
DotNetCompress version 3 is written in .NET 8, so ensure that you have that SDK installed. You can run commands like this to do the compression and replace the {folder}
placeholder with the folder where you want to compress files:
DotNetCompress -d {folder} -p "*.js" ".css" --format br --threads 8 --level SmallestSize
DotNetCompress -d {folder} -p "*.js" ".css" --format gz --threads 8 --level SmallestSize
The first command will compress all .css
and .js
files specified in the {folder}
placeholder using the Brotli compression, compressing them to the smallest size. The second command will repeat the process, but will use the Gzip compression.
Other drawbacks
So that's one way of compressing files from another folder. But there are other drawbacks with the static asset delivery optimisation feature.
Files have to be known at compile time. So if you have something like a dynamically generated XML site map, you won't be able to use it.
You also can't choose which files are compressed. This is a problem if you have a lot of static web assets as the total file size will increase.
A good feature will lots of potential
But it's a good feature and we're looking forward to what's to come. Being able to choose which files and folders are compressed would be a great addition. Maybe the option for minification to further reduce the file size?
Watch the video to see how the static asset delivery optimisation feature works in .NET 9 and see how it reduces the response time in Postman.