Skip to the content

Umbraco 9 .Net Core Bundling and Minification using Web Optimizer

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.

Gulp

Webpack

Web Optimizer

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.

app.UseWebOptimizer();
app.UseStaticFiles();

Then add this code to your 'ConfigureServices' method in your startup.cs file.

services.AddWebOptimizer();

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.

services.AddWebOptimizer(pipeline =>
{
    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.

services.AddWebOptimizer(pipeline =>
{
     pipeline.AddCssBundle(
          "/css/preload/bundle.css",
          "/Frontend/Styles/preload/*.css"
     );
     pipeline.AddCssBundle(
          "/css/bundle.css",
          "/Frontend/Styles/common/*.css",
          "/Frontend/Styles/webfonts/*.css",
          "/Frontend/Styles/*.css"
      );
});

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.

Bundle Wildcards

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.

pipeline.AddCssBundle(
     "/css/bundle.css",
     "/Frontend/Styles/common/*.css",
     "/Frontend/Styles/webfonts/*.css",
     "/Frontend/Styles/*.css"
);

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.

services.AddWebOptimizer(pipeline =>
{
     pipeline.AddCssBundle(
          "/css/preload/bundle.css",
          "/Frontend/Styles/preload/*.css"
     );
     pipeline.AddCssBundle(
          "/css/bundle.css",
          "/Frontend/Styles/common/*.css",
          "/Frontend/Styles/webfonts/*.css",
          "/Frontend/Styles/*.css"
     );
     pipeline.AddJavaScriptBundle(
          "/js/bundles.js",
          "/Frontend/Scripts/priority1/*.js",
          "/Frontend/Scripts/priority2/*.js",
          "/Frontend/Scripts/common/*.js",
          "/Frontend/Scripts/plugins.js",
          "/Frontend/Scripts/ajax-mail.js",
          "/Frontend/Scripts/main.js"
     );
});

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.

@using Umbraco.Extensions
@using Website
@using Umbraco.Cms.Web.Common.PublishedModels
@using Umbraco.Cms.Web.Common.Views
@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.

@import url("https://fonts.googleapis.com/css?family=Montserrat:200,300,400,500,600,700,800|Open+Sans:300,400,600,700,800");

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.

 pipeline.AddCssBundle(
     "/css/bundle.css",
     "/Frontend/Styles/common/*.css",
     "/Frontend/Styles/webfonts/*.css",
     "/Frontend/Styles/*.css"
);

Conclusion

'Web Optimizer' works great. I recommend trying this out.

You can also find some more details and tutorials for 'Web Optimizer' here.

https://github.com/ligershark/WebOptimizer

About the author

David Armitage

.Net MVC Developer
.Net Core Developer
Umbraco Certified Master
Recruitment Professional

Hey Peeps,

I'm an entrepreneur and web developer with a passion for coding. I absolutely love working with Umbraco CMS and appreciate the Umbraco community even more.

I've got 10 years+ .Net experience and 7 years+ experience working in the recruitment industry, both coding and marketing job websites. I wanted to use my skills to help give something back to this awesome community and so I decided to build UmbraJobs.com.

My vision & fundamentals

I want this website to be a place where Umbraco Professionals and Umbraco Partners can advertise their services but at the same time I want to filter out all the under-qualified freelancers & agencies that take up the biggest part of other job & freelancer websites. We've all worked hard to gain our Umbraco certifications, partnership status, and help build the Umbraco community to what it is today. I want to see everyone get rewarded for their efforts.

Follow me on social media

If you're an Umbraco professional, partner, employer, recruiter or a passionate Umbraco community builder then I'm more than happy to hear from you. Follow me on my social media channels and please reach out if you have any needs, want help or consultation with anything Umbraco related or just want a general chat.

comments powered by Disqus

Blog Filter


How we can help?

Need help with an Umbraco project?

Need help with a project but not too sure who to approach? Send us your project brief and budget. We will provide a free consultation and can help you gather quotes from the best and most suitable freelancers or agencies.

Looking to hire an Umbraco Professional?

Have you got job vacancy and want to hire an Umbraco professional? Post a job on our website for free. Alternatively let us know your requirements and we will send suitable prospects your way.

Claim your free profile!

Are you an Umbraco Freelance Developer or Umbraco partner that wants to advertise on our site? If you work with Umbraco or registered as an Umbraco partner then you can create a profile for free.

Let's build the Umbraco Community

We're big on building the Umbraco community and we think you guys are awesome! If there's anyway at all we can help then please reach out.