Angular Material Design custom build: include only the parts you need

I reduced the file size of my app’s dependencies by 15% by only including the Angular Material source code my app actually uses. This simple action improved page load speed and this should reduce bounce rate. As the app in question is another app’s marketing app/landing page, this improvement can have real monetary value.

The landing page is built with Angular Material (because so is the app it advertises). Angular Material is heading for feature parity with the components detailed in the Material Design spec. These features are awesome, but the landing page doesn’t use them all.

For the landing page, these unused features are wasteful: user wait for bloat to download that the app never uses. If we strip away unused features from our app then we can make the app load a little bit faster.

This post will explain how to easily make a custom Angular Material build using Gulp that includes only the needed features, without having to pull the Angular Material repo.

Angular Material Design “modules”

The Angular Material bower package comes with a “/modules/js/” folder, which has each of the components split into different source folders:

autocomplete
backdrop
bottomSheet
...
whiteframe

This makes it super easy for us to build only the components we need. We will need to do a bit of boilerplate to define the angular module that these components will live under.

Gulp

My build tasks looks something like below. When “buildDependencies” task is ran, it first finishes “buildMaterial” task, which creates “custom.js” in the angular material folder. “buildDependencies” task  then picks up custom.js and concatenate it with the other dependencies.

var insert = require('gulp-insert');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var DIR_JS_LIBS = './assets/js/libs';
var DIR_BUILD = './build/'
gulp.task('buildMaterial', function () {
    var modules = [
        'angular-material/modules/js/core/core.js',
        'angular-material/modules/js/core/default-theme.js',
        'angular-material/modules/js/backdrop/backdrop.js',
        'angular-material/modules/js/toast/toast.js',
        'angular-material/modules/js/sticky/sticky.js',
    ];
    var boilerplate = [
        '(function(){' +
        '    angular.module("ngMaterial", ["ng", "ngAnimate", "ngAria", "material.core", "material.core.theming.palette", "material.core.theming", "material.components.toast"]);' +
        '    })();'
    return gulp.src(modules, {cwd: DIR_JS_LIBS})
        .pipe(concat({path: 'custom.js', cwd: ''}))
        .pipe(insert.prepend(boilerplate))
        .pipe(gulp.dest(DIR_JS_LIBS + 'angular-material/'));
});

gulp.task('buildDependencies', ['buildMaterial'], function () {
    var deps = [
        'angular/angular.js',
        'angular-route/angular-route.js',
        'angular-ui-router/release/angular-ui-router.js',
        'angular-material/custom.js',
    ];
    return gulp.src(deps, {cwd: DIR_JS_LIBS})
        .pipe(concat({path: 'deps.min.js', cwd: ''}))
        .pipe(uglify())
        .pipe(gulp.dest(DIR_BUILD));
});

Outcome

The above example is a stripped down version of the real task. In reality the project uses about 7 components. After minifying I saw I saved about 60kb by using the custom build. This is approximately a 15% reduction.

This is not a huge saving, but it is worth the effort if continual improvement philosophy is followed then many small improvements can lead to great savings.

FWIW, click here to see my project using the custom Angular Material build. Its a marketing app for “Monofox Ask Peers” – basically a slimmed down private stack overflow for schools.