Skip to main content

Static file compression

Starting with Lagoon 4.0, static file compression is delegated to the .NET SDK's static web assets pipeline, and the toolkit overrides its default settings:

StepSDK default formatsFormats used by Lagoon
Buildgzipnone
Publishgzip + brotlibrotli only

Producing only Brotli significantly reduces the artifact size, but this format is negotiated by browsers only on a secure origin: HTTPS or http://localhost. On a remote http:// origin, the browser announces only gzip, deflate and cannot receive any of the published variants.

Application running over HTTP​

warning

If the application must be able to run over HTTP, add LagoonDefaultCompression to the solution's Directory.Build.props file.

Directory.Build.props
<Project>
<PropertyGroup>
<LagoonDefaultCompression>false</LagoonDefaultCompression>
</PropertyGroup>
</Project>

This property hands control back to the SDK, which restores its default formats: gzip during build, gzip and brotli during publish. The browser thus receives the gzip variant over HTTP and the Brotli variant over HTTPS.

Create the Directory.Build.props file at the solution root if it doesn't already exist.

danger

This is the only property to set, but it is essential. By default, Lagoon publishes only the .br variant of each compressed file: the original is deleted and MapStaticAssets returns it via content negotiation — on the Draft reference application, the published wwwroot folder thus shrinks from 23.8 MB to 10.4 MB. A client that does not accept Brotli has nothing to receive: the server returns 404 Not Found or an empty body, with no explicit error, and the application fails to start. Setting LagoonDefaultCompression to false restores the gzip variants and preserves uncompressed files.

Files that the Lagoon runtime reads directly from disk are never compressed and always remain present, regardless of configuration: the templates _vroot/index*.html and _content/Lagoon.UI/login-callback.html, the favicons favicon*.ico, service-worker-assets.js, and service-worker.js.

Why in Directory.Build.props and not in a .csproj​

Each project that has static files compresses its own wwwroot folder during its own build, and a property defined in a .csproj does not propagate to referenced projects. If placed in a single .csproj, the property would allow other projects in the solution to produce inconsistent variants. Directory.Build.props is inherited by all projects in the solution: it is the only location that guarantees consistent settings.

The file matters as much as the property: the toolkit's build files are imported before Directory.Build.targets, where the value would arrive too late to be read.

Verify the result​

After publishing, query a static file by varying the Accept-Encoding header:

# Client that accepts Brotli
curl -s -D - -o /dev/null -H "Accept-Encoding: br" http://localhost:5000/_content/Lagoon.UI/js/app-init.js

# Client that does not accept Brotli
curl -s -D - -o /dev/null -H "Accept-Encoding: identity" http://localhost:5000/_content/Lagoon.UI/js/app-init.js

The first request must return 200 OK with the Content-Encoding: br header. The second must return 200 OK without a Content-Encoding header and with a non-empty body: if it returns 404 Not Found or Content-Length: 0, the uncompressed variant was deleted during publishing, and the application will not work over HTTP. Then verify that LagoonDefaultCompression is indeed present in the solution's Directory.Build.props.

See also​