AngularJS + RequireJS + Filerevving generator

Facundo Ciancio
Monits’ tales
Published in
4 min readMay 18, 2015

--

Unless you like spending time creating the basic structure for each project you start, setting up its configuration and the tools/plugins/frameworks you’re going to use, we can agree that those tasks are terrible repetitive, tough and time-consuming. Using a generator will simplify most of these tasks, and will get them done in seconds.

That’s why we started to search for a generator that would provide us a way to generate projects with the two tools we love the most to build web applications: AngularJS and RequireJS. Why do we think these tools are great? Well, just to keep it simple, we could say:

  • AngularJS is an extraordinary framework that extends HTML to make it extremely easy to work with dynamic views in a modular way.
  • RequireJS lets your script files specify their own dependencies, load them asynchronously and on demand (lazy loading), which boosts performance, maintainability and reusability.

We found AngularJS generators and RequireJS generators, but none of them integrated the two correctly. The thing is, Angular is great to work in small modules (directives, providers, controllers, so on); which one would naturally want to load lazily as needed using RequireJS, however, due to the way Angular matches and uses them, bundling it with RequireJS is non-trivial, and most approaches we saw out there took the simplistic, and under performing approach of just bundling a whole module (which can even mean, a whole application) within a single RequireJS module. So much for lazy loading.

That’s why we decided to build it ourselves. We were going to do all the scaffolding and configuration stuff, but just once.

Was it easy? Not at all.

Angular + Require

Angular and Require were not developed having in mind the possibility of their own coexistence. While AngularJS’ dependency injection deals with the objects needed in a component, RequireJS deals with modules or Javascript files. When angular triggers dependency injection, it’s assuming all dependencies have already been loaded. Not even providers are allowed to return promises to the components, so the first challenge was to find a proper entry point.

After some struggle, and a trial and error period, we ended up discovering that we could return promises when resolving routes with Angular’s routeProvider. This was a great hook for lazy loading, every time a user navigated into some other page, we could just load the controllers, services and directives needed for that single page that hadn’t already been loaded. You can see an implementation of it here. It’s already being used in some of our productive projects.

Everything seemed to be working right until we decided that we wanted to improve it by doing serious file revving. Why? Because it is consider a must if you want to improve performance and we definitely wanted that. For those of you not versed with file-revving, it allows you to take advantage of browser caching capabilities by doing two things: first, you add expiring headers with dates in the very distant future to every file so browsers don’t have to download them twice. Second, when you modify those files, you change their file names forcing the browser to download the new version.

The first thought that came to our minds was: if we managed to integrate AngularJS and RequireJS, how difficult can it be? Well, it wasn't easy at all.

Integrating File revving

As I mentioned before, file revving changes your files’ name so browsers can detect when they have been modified. Doing this with images and CSS files is really easy. Getting it to work with the JS files loaded directly from HTML is too. But we are using AngularJS, and we want so much more! Templates themselves are just HTML snippets that should be completly cacheable! Even our AngularJS components are not going to change constantly, making them great caching candidates.

At the same time, we were using filenames to load Angular’s dependencies with RequireJS… And our AngularJS directives included the name of the HTML template to load. I hope you see the problem we had here.

We needed three things:

  1. Rev our files. ALL our files.
  2. Scrape all our JS, CSS and HTML files searching for references to absolute and relative paths to files and change them accordingly to the new names (this was the easy part).
  3. A way to tell RequireJS the actual name of each file after revving, so it can still resolve dependencies.

We ended up using usemin (with minor adjustments) to solve points 1 and 2, and we created a task on Grunt that does exactly what we needed for point 3: it searches for every .js file used and revved, generates a dictionary having its “clean” name (without the rev hash) as a key, and the reference to the “new” name as value, and writes that dictionary into a file that will be used to match filenames by Require when a dependency is needed.

What we ended up with

We created the “Angular Require Fullstack generator” (a yeoman generator) which comes to speed up the scaffolding of projects using AngularJS, RequireJS and File rev, plus some other cool (must-have) tools/plugins as Grunt, Bootstrap, i18n, file minification, Compass and Bower. We have made it available for download at npm.

How to use it?

To install generator-angular-require-fullstack from npm, run:

npm install -g generator-angular-require-fullstack

Finally, initiate the generator:

yo angular-require-fullstack

And it will guide you from there.

Have we finished it?

Certainly not. We will keep working on it and we welcome all the help you can provide us by giving us feedback on it, proposing changes and reporting issues.

If you like what you’re reading, and would like to work with us write to jobs at monits dot com with subject “Medium — Job opportunity”.

--

--

Facundo Ciancio
Monits’ tales

Ingeniero en Informática, Project Manager, Developer