Speed up CSS load on Umbraco 8

Cheap and Reliable Magento 2.0.4 Hosting

Speed up CSS load on Umbraco 8

With larger sites, it is usually the case that whole sections won’t ever be touched by a single user’s journey. This can unnecessarily add load time, and waste valuable seconds for users.

An easy solution to implement is code splitting, creating small bundles of CSS that are relevant to the section users are on. This can be further sped up by using Umbraco’s Client Dependency Module to stitch these tiny packages together, creating lightweight CSS files with little redundant code.

What we are going to do:

  • Create a gulp task that creates separate CSS files for each SCSS file
  • Use Umbraco & Client Dependency to render minimal CSS for each view

Getting Started

This is primarily a front end tutorial, so let’s assume that you have Umbraco set up and running. This tutorial has been tested on V8 of Umbraco, although the same process works equally well on V7 projects.

  • A basic understanding of using npm & the command line
  • A basic understanding of SCSS, and JS
  • A basic understanding of Umbraco Templates & Partials

Setting Up Gulp

To get started, we need to install gulp & the gulp-cli, so open up the cli in the root of your project:

npm install gulp-cli -g
npm install gulp gulp-autoprefixer gulp-sass gulp-changed -D

Gulp is a tool to automate repetitive tasks, and has endless plugins available for it. We have also installed:

  • gulp-autoprefixer which will handle prefixing for browser support for us
  • gulp-sass which converts SCSS down to CSS
  • gulp-changed which watches for file changes, speeding up further tasks

Next job is to create a gulpfile.js file in the root of our project. This is the base file where all tasks live.

As gulp files can turn to spaghetti pretty quickly, I prefer to split out all my tasks into reusable separate modules, so lets create a folder in the root called gulp-tasks and create a new js file in there called scss-compiler, that unsurprisingly will hold the code we use to compile SCSS.

The scss-compiler will contain a versatile task which creates a CSS equivelent version of each SCSS file, in the root CSS folder (which umbraco will have already created for us).

module.exports = function (gulp, sass, changed, autoprefixer, filePaths) {
    return function sassCompiler(done) {
        var sassPaths = [
            'node_modules/normalize.scss/sass',
            'node_modules/foundation-sites/scss'
        ];
         gulp.src(filePaths)
            .pipe(changed('css'))
            .pipe(
                sass({
                    includePaths: sassPaths,
                    outputStyle: 'compressed'
                })
                    .on('error', sass.logError))
            .pipe(autoprefixer({
                browsers: ['last 2 versions', 'ie >= 11'],
                cascade: false
            }))
            .pipe(gulp.dest('css'));
        done();

    };
};

What’s happening here? Well first, we are exporting the module, which we will later import into our main gulpfile. It expects arguments of the plugins required to run it, and the filePaths it is going to be processing.

The SassPaths holds any framework dependent styles, which in the example about, is for foundation sites.

Next gulp.src runs through each filePath supplied and:

  • changed checks if the file supplied has changes, else it will ignore it, saving valuable compiling time
  • sass (a.k.a gulp-sass) generates static CSS from the SCSS supplied, “compressed” meaning that it is smushed down to have minimal white spaces
  • autoprefixer will take any browser specific needs and prefix them for the specified browsers, for this case, its the last two versions of the Edge, Chrome and Firebox, and then IE11 up (so only…)
  • gulp.dest puts our transformed mini file in the css folder
  • done tells gulp that this task is finished, as Gulp runs asynchronously using promises, it needs a resolution to this promise.

In the gulp file, we need to first declare all of the packages we intend to use

// gulpfile.js
const gulp = require('gulp');const sass = require('gulp-sass');
const autoprefixer = require('gulp-autoprefixer');
const changed = require('gulp-changed');

Our newly created module can also be imported into the gulpfile

// gulpfile.js
const gulp = require('gulp');const sass = require('gulp-sass');
const autoprefixer = require('gulp-autoprefixer');
const changed = require('gulp-changed');const sassCompiler = require('./gulp-tasks/scss-compiler');

Which means we are all hooked up and ready to build our first task. As this will be our main task, we can use gulp’s default task, allowing us to just type gulp in the command line to run it.

To more easily allow us to run our SCSS tasks in parallel we can create a const to keep things tidy

const defaulSCSSTasks = gulp.parallel(sassCompiler(gulp, sass, changed, autoprefixer, 'scss/*.scss'));

We can run multiple tasks inside the parallel by comma separating them. Using “*” we can catch all files within a folder, making a robust and short directory for gulp to read through.

We add this new const into the default, and create a gulp watch to check for changes in the files.

const gulp = require('gulp');

// SCSS related requires
const sass = require('gulp-sass');
const autoprefixer = require('gulp-autoprefixer');
const sassCompiler = require('./gulp-tasks/scss-compiler');
const changed = require('gulp-changed');

const defaulSCSSTasks = gulp.parallel(
    sassCompiler(gulp, sass, changed, autoprefixer, 'scss/*.scss'),
    sassCompiler(gulp, sass, changed, autoprefixer, 'scss/views/*.scss'),
    sassCompiler(gulp, sass, changed, autoprefixer, 'scss/views/partials/*.scss')
);



gulp.task("scss", defaulSCSSTasks);

gulp.task('default', gulp.parallel(defaulSCSSTasks));

gulp.watch(['scss/*.scss', 'scss/**/*.scss', 'scss/**/**/*.scss', 'scss/**/**/**/*.scss'], defaulSCSSTasks);

My preference with structuring the SCSS is to follow the structure of umbraco templates:

scss/*.scss <-- Global files
scss/views/*.scss <-- Views
scss/views/partials/*.scss <-- Partials

This makes pairing files a piece of cake, each view and partial is paired up with its own SCSS file, keeping everything tidy. For bonus points, wrap each of your views and partials in a unique class, and enjoy the extra benefits of cascading styles and nesting.

// In your view or partial:
<div class="partial-name">
    <div class="foo">
        ...
    </div>
    <div class="bar">
        ...
    </div>
</div>// In your SCSS filepartial-name {
    .foo{
        ... specificity ;)
    }
    .bar{
        ...
    }
}

Dreamy.

One of the more tricky sides of this approach is that because each file is seperate when output, we need to make sure that they import global variables. This can be done by adding imports to the top of each file, as they only reference files with variables in, size isn’t affected with duplicate code.

@import 'settings'; 
@import 'foundation'; 

Again, the example above is for foundation, but the principle works the same for other frameworks.

Run your gulp file with gulp -w and all being well, you should have a host of CSS files in your CSSfolder.

The final piece of the puzzle is hooking up Client Dependency. Umbraco’s built in CSS and JS optimiser and compiler.

It comes with a host of handy features, and is well worth digging into to get the most of.

In your master template, (where ever your <head> lives), you will need to add

@using ClientDependency.Core.Mvc

Alongside your other using statements, and just before your closing </head> tag, you will need to insert

@Html.Raw(Html.RenderCssHere())

This is the injection site for the final <link> tag Client dependency generates.

Finally, in each view/partial that has it’s own styles, add in a reference to it’s css file at the top:

@using ClientDependency.Core.Mvc
@{
    Html.RequiresCss("~/css/carousel.css");
}

Now, sit back, and enjoy your speedy css.

While this technique creates Uber minified cached files on the fly in live mode, you get the pleasure of separate files for each CSS file while working locally, just make sure in your web.config you have debug="true" set.

You may from time to time need to give Client Dependency a kick, which is simple enough, just locate the config(Config/ClientDependency.config) and bump up the version number by one.

Anjali Punjab

error: Content is protected !!