AngularJS, RequireJS and HTTP/2 Push

May 10, 2016
Image

Summary

About ShimmerCat and AngularJS, RequireJS and HTTP/2 Push.

No costs implied

One question that many developers have is if Angular JS can be used with RequireJS. The answer to that question is “Yes”, but until now, it was also considered a bad practice, as opposed to bundling all the application’s scripts together. Bundling was considered a better option because it reduces the effect of network latency with HTTP/1.1

With HTTP/2, a smart and correctly configured web server can push the resources that make a page to the browser without costly round-trips. In this situation, RequireJS becomes a very sensible way to handle dependencies between the Javascript modules. Why? Because then the browser will be able to cache small individual files, so that if you change those files, returning users won’t need to fetch again the big bundles of resources that we usually build for old good HTTP/1.x.

In this post, we are going to get the hands dirty and explore how to do that in practice, using in the process our HTTP/2 web server ShimmerCat. We are going to setup a simple AngularJS + RequireJS project, and automate the process so that users can enjoy a faster website, even from high latency networks, and you as a developer only need to perform a minimum amount of work.

I should note that our server is not specifically tuned to RequireJS. We simply analyze the fetch patterns from the browser to create a dependency tree between resources. So, our server should work also with your favourite module loader, or with tools that can be configured to fetch resources to the browser like Handlebarsjs, Lesscss, and a few Javascript transpilers.

What you will need

I’ll assume that you have a full-fledged Linux 64 bit desktop available, with graphical user interface included.

The AngularJS + RequireJS project

This one is easy to setup, we are basically going to have a few files.

We are using for this example AngularJS v1.4.7, and RequireJS 2.1.22.

For convenience, I’m writing down the full structure of the files that we will have. But you are welcome to have your own structure.

<working-directory>-----+
                        |
                        devlove.yaml
                        |
                        www/ -----------+
                                        index.html
                                        |
                                        |--- js/
                                             |
                                             |--- require.min.js
                                             |
                                             |--- angular.min.js
                                             |
                                             |--- start.js
                                             |
                                             |--- app/
                                                  |
                                                  |--- mainController.js

Let’s start by the first file devlove.yaml which is the dreaded configuration file that all web servers need.

Here it is:

---
shimmercat-devlove:
  domains:
    www.httpdos.com:
        root-dir: www

The index.html is a very basic HTML file annotated with some angular tags. For this example, Angular bootstrapping is done manually, so you won’t see the ngApp tag.

<!doctype html>
<html>
    <head>
        <title>Hello world!</title>
        <script data-main="js/start" src="js/require.min.js"></script>
    </head>
    <body>
        <div>
          <div ng-controller="mainController">
            <label>Name:</label>
            <input type="text" ng-model="yourName" placeholder="Enter a name here">
            <hr>
            <h1>Hello !</h1>
            <p>Your name has  vowels</p>
          </div>
        </div>
    </body>
</html>

Then we have the minified versions of RequireJS 2.1.22 and AngularJS v1.4.7, and a simple start.js file that takes care of configuring both libraries:

require.config({
    shim: {
        'angular.min': {
            exports: 'angular'
        }
    }
});

define(["app/mainController", "angular.min" ], function(mainController, angular) {

    angular.element(document).ready(function() {
        angular.bootstrap(document, ["myApp"]);
    });

});

To make things slightly more interesting, we also have a mainController.js file:

define(["../angular.min"], function(angular) {

    var vowel_re = /[aeiou]/;

    function vowel_count(word) {
        if (word == null )
            return 0;
        var result = 0;
        for (var i = 0; i < word.length; i++ )
        {
            if ( vowel_re.test(word[i]) )
            {
                result += 1;
            }
        }

        return result;
    }

    angular.module('myApp', [])
      .controller('mainController', ['$scope', function ($scope) {
        $scope.vowelCount = vowel_count;
      }]);

});

In what follows, we are going to assume that you have deployed in a folder called /home/myself/myproject.

Running the server

For ShimmerCat to run your site, you need to take care of setting up certificates and some other details, please take a look at our getting started article.

To finally get the server running, use for example the following command:

$ cd /home/myself/myproject
$ shimmercat devlove

Finally, navigate to your site if you are using what we call “the old way”, or https://www.httpdos.com if you are using ShimmerCat’s built-in SOCKS5 proxy: “the progressive way” and see your application running.

We are almost there! The only thing missing now is asking the server to use HTTP/2 push to serve your resources in one shot. This is done by training the server. In future versions we may create a smoother workflow, but right now we need to tell the server commands which roughly mean “watch and learn!”, “meditate about what you have seen and use it to be faster”, and “now use what you know to serve pages faster”. Let’s go through it.

Learning and working faster

We are going to use sc-tool that takes care of changing server mode, training it, and then activating its high speed features. This uses browser automation, a nice technology that is part of day-to-day development for many front-end teams. You can see more details about it here. It is just a matter of running this command:

$ sc-tool learn -k www.httpdos.com www.httpdos.com

When you run the command above, you should see ShimmerCat handle you out an approximate dependency for your resources:

/index.html, /js/require.min.js, /js/start.js, /js/app/mainController.js, /js/angular.min.js

Here you see that RequireJS is triggering the load of file start.js when it analyses its own script tag. If you are looking to the Chrome’s devtools “Initiator” column in the network panel, you will see that Chrome is attributing the fetch of the other javascript files to RequireJS, but our server can identify that angular.min.js and mainController.js are loaded because start.js is requesting them. This knowledge opens all kind of interesting possibilities for managing resource caching wisely and painlessly.

Now, when you access your website, it should load faster in high-latency conditions. To know if a response is being pushed, you can look for a header x-shimmmercat-note: pushed-stream that ShimmerCat is inserting in the pushed responses.

Want help to optimize your product images with ShimmerCat?

Please fill in the form and we will provide you a free image report. We know the tech team already has a lot of other things to focus on

Get Image Report