Using GZIP Compression in ASP.NET Core
GZIP is a generic compression method that can be applied to any stream of bits. In terms of how it’s used on the web, it’s easiest thought of a way that makes your files “smaller”. When applying GZIP compression to text files, you can see anywhere from 70-90% savings, on images or other files that are usually already “compressed”, savings are much smaller or in some cases nothing. Other than eliminating unnecessary resource downloads, enabling compression is the next best way to improve the loading speed of your web app.
Enabling At The Code Level (Dynamic)
You can dynamically GZIP text resources on request. This is great for content that may change (Think dynamic html, text, not JS, CSS). The reason it’s not great for static content such as CSS or JS, is that those files will not change between requests, or really even between deployments. There is no advantage to dynamically compressing these each time they are requested.
The code you need to make this work is contained in a nuget package. So you will need to run the following from your package manager console.
Install-Package Microsoft.AspNetCore.ResponseCompression
In your ConfigureServices method in your startup.cs, you need to add a single line to add the dependencies that GZIP compression is going to need.
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddResponseCompression(); }
Note that there are a couple of options you may wish to use in this call.
services.AddResponseCompression(options => { options.EnableForHttps = true; options.MimeTypes = new[] {"text/plain"}; });
The EnableForHttps flag does exactly what it says. It enables GZip compression even over SSL (By default this is switched off). The second turns on (Or off in some cases) GZip of certain mimetypes. The default list at the time of writing is the following (Taken from the Github source here) :
"text/plain", "text/css", "application/javascript", "text/html", "application/xml", "text/xml", "application/json", "text/json",
Then in your configure method of startup.cs, you then just need a single line to get going.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseResponseCompression(); app.UseMvc(); }
Note that the order is very important! While in this case we only have two pieces of middleware that don’t cause issues, other middleware (such as the Static Content middleware), actually send the response back to the user before GZip has occured if it’s first in the list. For safety sake, just keep UseResponseCompression as the first middleware in your list.
To test you have everything up and running just fine, try loading your site and watching the requests go past. You should see the Content-Encoding header come back as “Gzip”. In Chrome it looks like the following :
Enabling At The Code Level (Static)
The issue with enabling GZip compression inside .net core is that if your content is largely static (As in it doesn’t change), then it’s being re-compressed over and over again. When it comes to javascript and CSS, there is really no reason for this to be done on the fly. Instead we can GZip these files beforehand and deploy them “pre” GZip’d.
For this you will need to use a task runner such as Gulp to GZIP your static files in your pipeline. There is a very simple gulp package for this named “gulp-gzip”. Have a search around and get used to how it works. But your gulp file should look something similar to the following :
var gulp = require('gulp'); var gzip = require('gulp-gzip'); gulp.task('gzip', function () { return gulp.src('wwwroot/scripts/app.js') .pipe(gzip()) .pipe(gulp.dest('wwwroot/scripts/')); });
This is a very simple case, you will need to know a bit more about Gulp to customize it to your needs.
However importantly, you need to map Gzip files to actually return their real result. First install the static file middleware. Run the following from your Package Manager console.
Install-Package Microsoft.AspNetCore.StaticFiles
Now in your Configure method in startup.cs, you need to add some code like so :
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = content => { if(content.File.Name.EndsWith(".js.gz")) { content.Context.Response.Headers["Content-Type"] = "text/javascript"; content.Context.Response.Headers["Content-Encoding"] = "gzip"; } } }); app.UseMvc(); }
What does this do? Well first it says that serving static files without running the MVC gamut is A-OK. But next it says, if you come across a file that ends in .js.gz, you can send it out, but instead tell the browser that it’s actually javascript and that it’s just been encoded with gzip. Otherwise it just returns the file as a plain old GZip file that a user could download for example.
Next on your webpage, you actually need to be referencing the .gz file not the .js file. So it should look something like so :
<script type="text/javascript" src="/scripts/app.js.gz"></script>
And that’s it, your static content is now compressed!
Enabling At The Server Level
And lastly, you can of course always enable GZip compression at the web server level (IIS, NGinx, Apache etc). For this it’s better to consult the relevant documentation. You may wish to do this as it keeps the configuration out of code (And allows a bit more easier access for configuration on the fly).
No comments