Using RequireJS With Optimisation For Lazy Loading AngularJS Artefacts

May 27, 2013 — 9 Comments

Being able to lazy load artefacts such as controllers and directives in AngularJS is great because in addition to saving on bandwidth costs, it results in the initial load time of your AngularJS app being much shorter. This is because only the assets that are needed to render the particular route in question, are delivered to the browser, and nothing more. If too many files are being lazy loaded at a time, however, the time between the initial load of your app and when the app is actually ready to present its first route, may significantly increase. The same applies for the time it takes to change routes. This can happen when the browser has reached its ‘maximum concurrent connections’ limit and as a result, has to wait for the first set of concurrent downloads to complete before starting another set of downloads. One way to mitigate this issue is to present some sort of ‘loading’ message to the user while the lazy assets are being loaded. At times, however, the message may not be enough to maintain the perception of the app being performant. At this point, the only thing that can then be done is to combine the lazy assets into fewer files that can be delivered much faster to the browser.

This is where RequireJS comes in. RequireJS is a JavaScript file and module loader that also comes with an optimisation tool that can be used to combine module definitions into ‘optimised bundles’ for fast delivery to the browser. When partnered with Grunt (a JavaScript task runner), it can be easily used as part of your build step to package multiple lazy AngularJS artefacts into fewer files. Using the lazy loading strategy found in my previous article entitled ‘Lazy Loading In AngularJS‘, I have created a runnable sample project that demonstrates grunt being used with RequireJS to combine lazy dependencies into optimised bundles. The sample project can be found at:


Ifeanyi Isitor

Posts Twitter Google+

I'm a web application developer / independent contractor, currently residing in London.
  • wburningham

    Awesome work. It is great to have simple boilerplate like this.

    How do you develop with this setup? Since the requirejs paths are in the gruntfile.js you would have to build each time you wanted to see your changes. Do you normally put the requirejs config in a separate file?

    • John Kennedy

      You can set grunt to watch for changes in your files so it will build automatically on each save. Very handy if you are using compiled CSS like LESS or SASS. Or coffeescript if you’re one of those ;)

      • Prashanth S

        But it takes lot of time to reload the page with watches.

    • ifeanyiisitor

      Thanks. I have only recently started playing with requirejs optimisation via grunt and at the time it was easiest (for me at least) just to have the config in grunt itself. Having said that though I do feel that it is a good idea to have the requirejs config outside of the grunt file so that the app could at least be run without being optimised, for easier debugging. I plan to soon make the changes. For now though, the grunt file also contains a watch task that can be invoked with the command grunt watch. Once started, all changes will cause a rebuild (as also stated by John).

  • Thomas Thiery

    Do you have any benchmark with a small API and a largest, I’m very curious about the performance loading?

    I ask you this because some people say it’s not important to do asynchronous lazy loading, like this stack overflow post :

    For these :

    1. Synchronous loading with all js

    2. Asynchronous loading with all js

    3. Lazy loading with no optimize js

    4. Lazy loading with optimize js

  • Pranav K

    Very helpful article…

    One observation, when you navigate away from home link i.e. about/me and try to refresh browser it throws 404. Let us know how to resolve this.

  • Rajesh

    It looks interesting but i couldn’t run sample project. I get this error “Uncaught Error: Mismatched anonymous define() module: undefined” for dependency modules.

  • Prashanth S

    Hi your blog helped me a lot. But can you please explain how bower/yeoman/grunt works with this approach. Using grunt task i am able to minify/concat the files which are in index.html but what about the files which are loaded async via approutes? Any sugg or workarounds?

  • Alan Snow

    I could really use your help with one of your articles on the lazy loading! Please contact me, my name is Alan, if you have google chat my username is or if you are a mac user my apple id is or I would really appreciate it if you could reach out as soon as you can. I feel your knowledge could really help me!