Skip to content

Commit

Permalink
Add support for Zstd compressed static files (#52)
Browse files Browse the repository at this point in the history
Allow serving Zstd compressed files with the `.zst` extension.

The example has not been adjusted yet, because the SDK's supported CompressionFormats do not yet include zstd. However, static files compressed by other means (external tools) still work.

Rationale:

[Chrome 123 added zstd Content-Encoding support behind a feature flag `enable-zstd-content-encoding`](https://chromestatus.com/feature/6186023867908096), and [Mozilla has committed to implementing it in Firefox as well](mozilla/standards-positions#775).

Co-authored-by: Jeremy Kescher <jeremy.kescher@timetoact.at>
  • Loading branch information
kescherCode and Jeremy Kescher authored Mar 13, 2024
1 parent f2c05fd commit c15055f
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public class CompressedAlternativeFileProvider : IAlternativeFileProvider
new Dictionary<string, string>()
{
{ "gzip", ".gz" },
{ "br", ".br" }
{ "br", ".br" },
{ "zstd", ".zst" }
}.ToImmutableDictionary();


Expand All @@ -45,6 +46,7 @@ public void Initialize(FileExtensionContentTypeProvider fileExtensionContentType
{
// the StaticFileProvider would not serve the file if it does not know the content-type
fileExtensionContentTypeProvider.Mappings[".br"] = "application/brotli";
fileExtensionContentTypeProvider.Mappings[".zst"] = "application/zstd";
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,7 @@ private void ProcessRequest(HttpContext context)
//Find the smallest file from all our alternative file providers
var smallestAlternativeFile = _alternativeFileProviders.Select(alternativeFileProvider => alternativeFileProvider.GetAlternative(context, fileSystem, originalFile))
.Where(af => af != null)
.OrderBy(alternativeFile => alternativeFile?.Cost)
.FirstOrDefault();
.MinBy(alternativeFile => alternativeFile?.Cost);

if (smallestAlternativeFile != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Files need to be compressed and converted to other image formats before deploying.
</Description>
<PackageProjectUrl>https://github.com/material-blazor/CompressedStaticFiles.AspNetCore</PackageProjectUrl>
<PackageTags>aspnetcore;staticfiles;compression;precompressed;gzip;brotli;zopfli;webp;avif;</PackageTags>
<PackageTags>aspnetcore;staticfiles;compression;precompressed;gzip;brotli;zopfli;webp;avif;zstd</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageReleaseNotes></PackageReleaseNotes>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ This project allows you to serve precompressed files to the browser without havi
## Getting Started

### Precompress content
Static nonimage files have to be precompressed using [Gzip](https://en.wikipedia.org/wiki/Gzip) and/or [Brotli](https://en.wikipedia.org/wiki/Brotli), see CompressedStaticFiles.Example.csproj for an automated methodology for producing compressed css & js files.
The files must have the same filename as the source + `.br` or `.gzip` (`index.html` would be `index.html.br` for the Brotli version).
Static nonimage files have to be precompressed using [Gzip](https://en.wikipedia.org/wiki/Gzip), [Brotli](https://en.wikipedia.org/wiki/Brotli) and/or [Zstd](https://en.wikipedia.org/wiki/Zstd), see CompressedStaticFiles.Example.csproj for an automated methodology for producing compressed css & js files.
The files must have the same filename as the source + `.br`/`.gzip`/`.zstd` (`index.html` would be `index.html.br` for the Brotli version).

### Encode images
Modern browsers support new image formats like webp and avif they can store more pixels per byte.
Expand All @@ -55,7 +55,7 @@ Replace `UseStaticFiles();` with `UseCompressedStaticFiles();` in `Startup.Confi
By default CompressedStaticFiles is configured to allow slightly larger files for some image formats as they can store more pixels per byte, this can be disabled by calling `CompressedStaticFileOptions.RemoveImageSubstitutionCostRatio()`.

## Example
An example can be found in the [Example](https://github.com/material-blazor/CompressedStaticFiles.AspNet/tree/main/CompressedStaticFiles.Example) directory.
An example with Gzip and Brotli can be found in the [Example](https://github.com/material-blazor/CompressedStaticFiles.AspNet/tree/main/CompressedStaticFiles.Example) directory.
By using this package the Lighthouse mobile performance went from `76` to `98` and the transferred size went from `526 kb` to `141 kb`.

## Acknowledgements
Expand All @@ -67,4 +67,4 @@ We built this cloned project because:

- We wanted to update to the currently supported version of .NET;
- To make some refinements that were to our taste; and
- To add MSBuild code to the [example CSPROJ file](https://github.com/Material-Blazor/CompressedStaticFiles.AspNet/blob/main/CompressedStaticFiles.Example/CompressedStaticFiles.Example.csproj#L13) to build Brotli and Gzip compressed CSS and JS files.
- To add MSBuild code to the [example CSPROJ file](https://github.com/Material-Blazor/CompressedStaticFiles.AspNet/blob/main/CompressedStaticFiles.Example/CompressedStaticFiles.Example.csproj#L13) to build Brotli, Gzip and Zstd compressed CSS and JS files.

0 comments on commit c15055f

Please sign in to comment.