What is bundling and minification?
Bundling and minification are two techniques to optimize your static assets (generally css and js).
What is Bundling?
Bundling is a process of 'bundling' all your js or css files into one. This optimizes your website's load time and gets you some valuable points on the likes of Google Page Insights. 'Bundling' all your js and css files in to one reduces the number of servers requests. The less (unnecessary) servers requests your web application or website has the better.
What is Minification?
Minification is a process of compressing your js and css files, mainly by removing all unnecessary space, line breaks and comments. When you download jquery plugins you may notice there is often a js and a min.js file. The benefit of minifying your js and css files is it simply reduces the file size of these assets. This in turn means less for the browser to download and faster your website or web application loads.
Different ways of handling bundling and minification in Umbraco 9
There are a number of was to handle bundling and minification. All have their pros and cons and it seems to mainly come down to personal preference. Here are a few popular options.
All these options seem equally as popular. My preference for this article is 'Web Optimizer'. I have noting against the other options and I have used and like each of them.
The main reason I have chosen Web Optimizer is for simplicity in the configuration.
I find the other options especially 'Gulp' has some benefits over 'Web Optimizer' but the learning curve and the configuration is a little bit more complex. To configure 'Gulp' it's quite straight forward if you are used to working with it. If not then the configuration options can be a bit overwhelming. I found when working with large teams that not everyone has experience with Gulp and I've had to spend a lot of time getting team members up to speed and making sure their environment has everything installed to support this.
With 'Web Optimizer' I like the fact that the config is very straight forward and 'Web Optimizer' is installed through Nuget. It can then be checked into Git. When team members pull from git everything just works nicely without any understanding of what's going and without installing any third party software in their local environment.
I also like that the config is stored directly in the startup.cs. I like this firstly because we don't need to add any extra config files and. Secondly I think this makes it very easy to spot how the bundling and minification is handled since we are often in and out of the startup.cs file and the config is very simple as you will see below.
One other thing I like is the bundle files are created in memory. I've found in the past when there's physical bundle files there is always the change that developers might try and edit the css and js within the bundle file. Especially if they have not been told they need to install 'Gulp' when take over in existing project.
Anyway, that's the mean reasons my preference here is 'Web Optimzer'.
How to configure Bundling & Minification in Umbraco 9 .Net Core
Configuring is really easy. The first step is to install a nuget package to your project.
Step 1 - Install Nuget Package
dotnet add package LigerShark.WebOptimizer.Core
Step 2 - Enable Minification
Add these settings to the 'Cinfigure' method in your startup.cs file.
Then add this code to your 'ConfigureServices' method in your startup.cs file.
That's it! As easy as that
You now have minification of your js and css files automatically on the fly. If you run your project and inspect a css file you will see this has automatically been minified.
Step 3 - Bundling your CSS Files
Bundling your css file is also a very simply process. Replace the code in step 2 with the following.
pipeline.AddCssBundle("/css/bundle.css", "css/a.css", "css/b.css");
The first path where you want your bundle to be located. As I previously said, this will be in memory so there will not be a physical file. If you visit the URL /css/bundle.css you will see that it works even though there is no physical file at that location.
The other paths are the files you want to add to the bundle.
Step 3 Extras - What I like to do
Adding CSS above and below the fold
If you are like me and pay particular attention to optimization and page speed then you might split your css up into two. Above the fold and below the fold. So you might like to have a small css file load first in the head of your website then have the rest of the css load at the bottom after everything else. This is a really good practice if you are interested in improving your on-page optimization.
To do this I create two bundles. Eg.
So as you can see I have created two bundle files "/css/preload/bundle.css" and "/css/bundle.css". I will put the preload in my page head and I will out the other bundle file at the bottom just before the body close tag. I wont get into what my preload css files contain but you can google good techniques relating to 'above the fold' css.
I set up bundle configuring in a way that I don't need to keep revisiting I every time I add a new css file. I do this by using the '*' wildcard.
So if you examine the code here.
So what is happen here is
I am creating a "/css/bundle.css" in memory.
This bundle is made up of...
All the css files stored in "/Frontend/Styles/common/",
All the css files stored in "/Frontend/Styles/webfonts/"
All the css files stored in "/Frontend/Styles/".
In that order
Step 4 - Bundling your JS files
Bundling JS files might require a bit of pre planning. As you know the order of JS files can be very importing. Some JS files might need adding before all others (jquery.js etc).
To work around this I use a similar technique to like I touched on in Step 3 Extras above.
If you examine my code below you can see I have used the '*' wildcard. I am first bundling all the js files in 'priority1' then 'priority', then 'common', then finally the 'Scripts' root.
Doing this will keep the priority exactly how I wont and I will get around ant referencing issues.
If not doing it this way I think the bundler just ads them in the same order as they are in the directory which might not be ideal in every case.
Step 5 - Enable Caching
Its a great idea to cache your static css and js files. 'Web Optimizer' does this out of the box but there is one extra step you need to do to enable this.
Locate the file in your project called _ViewImports.cshtml in the Views/Partials folder.
And add the following line of code.
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
So your file would look something like this.
@addTagHelper *, WebOptimizer.Core
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Now if you build and run your project will you notice your bundle files now look slightly different. Something like this.
<link rel="stylesheet" href="/css/bundle.css?v=OFNUnL-rtjZYOQwGomkVMwO415EOHtJ_Tu_s0SIlm9s" />
'Web Optimizer' adds a version number to the end (?v=) and this will be cached.
If you make any changes to the files within the bundle you will notice the version changes and then your new version will get added to the cache.
Extras - Using the 'inline' tag helper
First off I will mention you must complete step 5 for this to work. Basically tag helpers must be enabled as step 5 guides you through.
If you do like to add cut back versions of your css above the fold then this will be a create tag helper for you. This allows you to not only add your css above the fold in the head but also make it inline css which is one step better.
To do this simply add the 'inline' tag helper to your bundle or css reference. Eg.
<link rel="stylesheet" href="/css/preload/bundle.css" inline />
Warnings - Watch out for this
One negative to 'Web Optimizer' is the bundling doesn't act so great when dealing with imported web fonts. If you like to import fonts in to your css like this.
Then you will notice this breaks the minification. The style still seems to get applied but ig you look in your bundle file you will notice the minification is broken.
Bottom line is don't import fonts this way. Alternatively, what I have found works is by downloading the font css file and include it locally.
So if you visit the url in the import above you will see that its simply a css file. Download the css file, same it in your project and add it to the bundle. You may have noticed in my example about that I included all the files in 'webfonts' into the bundle. This is why.
'Web Optimizer' works great. I recommend trying this out.
You can also find some more details and tutorials for 'Web Optimizer' here.