Although the concepts and issues have been around for a while, the use of such terms as “dependency management” and “package management” has exploded exponentially since ~2013 and is now part of every JavaScript developer’s vocabulary (and yes; they do mean different things!). But what the deuce do they mean, and what issues are they addressing? Let’s find out…

Quick note: This whole post is going to refer to both of these concepts from the point of view of JavaScript.

Package management

We’ll start with package management. What are “packages” and why do they need managing? A package simply means a piece of code (in real black and white terms).

disappointed looks

Yep, really.

jQuery can be a package. That dodgy hack you wrote to handle pushState can be a package. External packages are commonly 3rd party pieces of code, or vendor libraries. A jQuery plugin is a perfect example of a package. Internal packages more often refer to units of code you’ve separated out into it’s file. Maybe you wrote some code to make working with cookies easier, all this code would go into it’s own file and you may include it with a <script></script> tag. So, we know what packages are, now why/how do we “manage” them.

Ok, so you’ve started your project, you’ve made your index.html file and now you decide you want to use jQuery. You either, a) find Google’s jQuery CDN link and whack it into a <script></script> and start using it, or b) you head over to the jQuery site and download a zip file or a JS file which contains the jQuery source code and drag it into your project’s scripts folder, then add your <script></script> tag. Both valiant methods and shall not be discouraged around these ‘ere parts. There’s not really a lot to manage here, you’ve got one file, one package (jQuery) and you’re the only developer. Now fast-forward and you’ve started working on this project with a team, and the number of “packages” has increased from 1 to 30? 40? 50? Entirely reasonable. For each one you’ve scoured GitHub repositories, navigated the wilderness of zip downloads and can still see the word “CDN” when you close your eyes. Again, these are fairly insignificant problems in the bigger picture, however, when you’ve got deadlines looming or a new feature to release, and a colleague has “helpfully” updated the version of jQuery that you’re using without you noticing, it can lead to hellish losses of productivity/hair.

There are numerous tools to help you manage these “packages”. To keep things simply, I’m going to use Bower to illustrate using a package manager. (I will link to other package managers at the end of this post).

Bower markets itself as a “package manager for the web”, which is handy, because that’s what we want. To get started with Bower, we need to first make sure we have Node.js installed on our machine. If you haven’t, head over to http://nodejs.org/ and hit “Install”. The whole process should take ~1 minute and you’ll be ready to go. Open up the command line and type npm install bower -g. Now you may find this mighty odd, but we’ve just used Node.js’s own package manager (npm) to install Bower (a package manager). Bear with me. By adding on -g to the end of the command, we’ve told npm to install Bower globally. Simply put, this means we can use it everywhere on our machine. Now you’ll need to find your project folder (create a new folder somewhere if you haven’t already). Make sure it has an index.html file inside it (not necessary for Bower, but needed for the next step). Then type into the command line bower install jquery. A load of Matrix stuff should happen and hey presto, you should have a new folder inside your project directory called bower_components. Now, you’re not banned from doing stuff in this folder, but as it’s managed and generated by Bower, I’d just let Bower do its own thing in there. If you look inside it, you’ll find a folder called jquery and inside that, one called dist and inside that, some files. Nice, now we have the actual package installed into our project. If you head back over to your index.html, you can now pop a <script></script> tag in there, with the src attribute set to /bower_components/jquery/dist/jquery.js and start using jQuery. Neat huh?

As this is supposed to be a high-level look at package managers and dependency management, I’m not going to go too much into using Bower. But if you want to adopt Bower into your workflow/project, then you’ll find the docs a damn fine read. You’ll soon be installing, uninstalling, searching, updating and making new Bower packages in no time.

Other package managers you can use:

Dependency management

Now you’re a package managing maestro, you fingers must be getting pretty tired typing out <script type="text/javascript"></script> over and over again, right? And all those script tags won’t be great for our end-user, will they? All those HTTP requests. Well, you can just concatenate all the files together when you want to publish your project, right? Well, you can, but you must specify some sort of order for concatenation, because myPlugin.js needs theirPlugin.js to be loaded before it can run, and oh no we now have a mess again.

Now, before we jump in to solving the spaghetti mess above, what exactly do we mean by a “dependency manager”? I mentioned that myPlugin.js needs theirPlugin.js to be loaded before it can run, so myPlugin.js has one dependency: theirPlugin.js. It relies on this file being present for it to run. Ok, well you just add two script tags, make the first one point to theirPlugin.js and the second one point to myPlugin.js, so that way, we, ourselves, have specified the order of the files being loaded and have manually managed the dependency. Crisis averted. And for a while, these measures are fine, and you can carry on being your own dependency manager, but there’s (probably) going to come a time where you start working with more people, the codebase grows, complexities increase and this process isn’t feasible or scalable. Well, luckily for us, there are tools to manage these dependencies for us, all we need to do is tell it what we need and let it do it’s job. Again, there are many of these tools, but the one I’m going to use to illustrate my point in this post is Browserify.

Browserify aims, along with all the other tools, to solve the same problem, but approaches the problem in a different way. I’m going to show you how to use Browserify as a means to introduce you to dependency managers, but hopefully, once you’re comfortable with the idea, you’ll pick the tool that you agree with the most and find easiest to use/adopt.

Browserify allows you to use CommonJS modules in the browser. Great Scott! Let me explain. Imagine we’re writing a new piece of functionality in our application, and we want to be good citizens and separate out our new code into it’s own file. So we’ve hit the same fork in the road as before; how do we load this onto the page. Script tag? Not this time. We’re going create one file: main.js in our project directory (we’ll need this later). We’re then going to create myModule.js in the same directory. We fill myModule.js with this bit of code:

var array = [1, 3, 5];

array.map(function(item){
	return item * 2;
});

module.exports = array;

That looks pretty standard, expect from the last line, module.exports. The browser will freak out when it hits this line, where did we even define module, let alone module.exports?? This is what Browserify does, it converts source code (like above) into browser code that can be ran in a normal browser.

In our module above, what do we do if we want to use Underscore.js? We could download it from Github? A CDN? Aha - use a package manager. I’m going to use npm with Browserify. So head over to the command line, find your project directory and type in npm install underscore. Cue Matrix green writing and there, we now have a folder called node_modules in our project, which will contain a folder called “underscore”. This should ring some memory bells as we completed similar steps with Bower above. However, this is where dependency managers kick in and we no longer have to add several <script></script> tags to our index.html page. Remember what I said, we tell the dependency manager what we want, and let it worry about including it on the page. So if we change the above code to this:

var _ = require('underscore');

var array = [1, 3, 5];

_.map(array, function(item){
	return item * 2;
});

module.exports = array;

We now have a more complete module, which makes showing you how Browserify works, a lot easier. You’ll notice we’ve added a new function, require. Which, again, we’ve not defined anywhere, and would error if we ran this code in the browser. Browserify will look at this file, see the require function, go find Underscore.js and let us use it below. No more script tags, we just tell it what we need and it’ll sort the rest. By downloading Underscore.js using npm, Browserify knows to look in the nearest node_modules folder it can find for the appropriate module (a simplified explanation for the purposes of this post, it does far more clever things than just that). So we’re using the power of a package manager to pull in code to our project, then we’re using a dependency manager to use that code in our application.

The next step will hopefully clear up the use of module.exports. If we open up our main.js and type in:

var myArrayFromMyModule = require('./myModule.js');

console.log(myArrayFromMyModule); // [2, 6, 10]

As you can see, whatever you assign to module.exports gets pulled in via the require function and placed in the myArrayFromMyModule variable in main.js. You can put most types onto this module.exports object, depending on your specific needs, whether it be a function, or an object literal ({}), or simply a number. You’re now writing CommonJS modules, which is a well established design pattern.

You may have noticed that we haven’t, so far, told our index.html to load any of the JavaScript we’re writing, or actually used Browserify for anything. Let’s do those now. Browserify works by you giving it your project’s main JavaScript file, in this case, is our main.js then it will look at main.js, find all the require functions and bundle them all up into one new file, which you link to in your index.html file. How do we do that?

Firstly, we need Browserify on our machine. We can do this by (again, making sure we Node.js installed) opening up the command line and typing:

npm install browserify -g

just as we did with Bower. Again, note the -g on the end, which lets us use Browserify anywhere.

Now we have Browserify, we can navigate into the project directory on the command line and type in:

browserify main.js -o bundle.js

This tells Browserify which is our “main” file (which coincidentally is actually called “main.js”) and what file to create with all of our code in it. Convention is to call it bundle.js, as Browserify bundles all the dependencies up for us, but it really doesn’t matter what you call it, you could even write: browserify main.js -o spongebobsquarepants.js and it would just create you spongebobsquarepants.js without passing any judgement. We can now open up our index.html file and add one, yes one, script tag:

<script type="text/javascript" src="bundle.js"></script>

Which, if you open your project up in a browser, should execute perfectly!

Wrap up

I’m hoping that you’re now a bit clearer on what a dependency manager is and what a package manager is, but most importantly, the problems they’re both trying to solve. Once you do some initial set up work a few times, you may find that you start using both on projects right from the outset. My personal flavour of choice is the combination of using npm to download/manage packages, and Browserify to bundle up my dependencies, and now I’ve got them both installed on my machine, there’s almost zero set up for a new project. I’m also well aware that I’ve not mentioned many different tools in this post, but I think it’s more important to gather the understanding of what problems you’re solving and then let you pick your own tools.