The never ending journey.

As a lot of you might have had as well, I’ve had a lot of problems with managing my javascript dependencies. There are a lot of ways you can do it, but most of them either require a lot of work, or have too many dependencies to work with.

I’ve searched long and hard, trying to find the best solution. I’ve come across Require.js, browserify, grunt and many more, but these were the best solutions in the bunch. Here are some of my findings on these three.

Require.JS

Require.JS is different in that it’s mainly meant to do AMD loading. It allows you to do some cool things, and actually works quite well. The problems I have with require.js are as follows:

  • It forces you to wrap your code in a function call.
  • It forces another (quite large) dependency on you.
  • It’s difficult to add non-AMD dependencies.
  • When a non-AMD dependency requires the use of another non-AMD file, good luck.
  • When you want to add unit tests you’ll have to work around require.js.

It’s good, but not good enough for me.

Browserify

Browserify looks very appealing when you look at it for the first time. Using require calls in my front-end javascript!? Yes please! Unfortunately, after trying to work around it for quite a while, I’ve found a couple of pretty upsetting drawbacks:

  • It’s a bit fragile and doesn’t always do what you’d expect.
  • It makes generating code coverage a tad difficult (it doesn’t recognize the require calls).
  • It forces a dependency on you.

It’s better than require.js, but still not good enough.

Grunt (concat, usemin)

GruntJS, the task-running bamf. It’s amazing in that grunt itself doesn’t manage your dependencies for you, the plugins do. So this is actually a comparison between two of the best plugins I’ve found.

usemin

Usemin allows you to add good old script tags to your html, and html comments to figure out where to put the combined file. This is pretty cool, but it’s only cool when using static html files as it rewrites your html for you. I was able to still implement this, have it write my views to a different directory and tell my app to use those views. This worked okay, but still felt a bit weird and dirty.

concat

grunt-contrib-concat, the best I’ve found. This plugin is really straight forward. Specify the javascript sources, and where (what file) you’d like to put them. It just concatenates a list of scripts, and allows you to supply wildcards, too (the way grunt does). This is super simple, and actually is all anyone would ever need. Downside? It requires quite a bit of extra work as you’ll always have to update the task in the gruntfile whenever you add a new dependency and also forces you to keep a mapping between those files and the gruntfile so you don’t end up with orphans.

In comes useuses

Tired of looking through all these alternatives I decided it was time to write something myself. I called it useuses because it allows you to use uses. Aren’t I creative?

What it is.

Before I started writing this plugin, I assembled a list of requirements:
* It must be optional.
* It mustn’t force a dependency upon someone.
* It must be “standard”, so no weird tags.
* It must add value to the files, even when not used.

With those requirements set, I came up with a way to specify what dependencies a file has, to make it informative for the developers. So as soon as you were to open up a file, you’d immediately see what it depends on. This made me think of the way jquery ui does that. It’s nice, but not nice enough. It’s still unformatted information.

The syntax

I finally came up with the following syntax:

This is informative and standardized in the docblock format. I immediately added support some other formats:

Conclusion

I liked all alternatives and think that the developers did a great job creating solutions. I think that whatever you decide to use depends on your project’s requirements and development style.

If you wish to give useuses a go, you can find the npm package for useuses by clicking here.

Happy coding.