Why requirejs?

Why are we using requirejs? I've even asked it of myself. For me, organizing large javascript projects and managing dependencies led to it. There are lots of great posts about how to use requirejs but I wanted to focus on WHY.

Explicit Dependency Specifications

Open up any significant sized javascript file with 100+ lines of code, even 50, and tell me, within 5 seconds, what dependencies it has. Can't do it? You can with modules and requirejs.

function View() {
    this.name = ko.observable('bob');
    this.age = ko.observable(20);
var view = new View();
ko.applyBindings(view, $('viewPlaceHolder')[0]);    


require(['jquery', 'knockout'], function($, ko) {
    // who knows whats in here, but I do know what it needs

How often do you use this information as a developer? Think about the value in not spending 5 minutes everytime you need to know, or more likely, the value in not creating a bug because you didn't take the time to find them all or you missed one.

Explicit Export Specifications

Along with explicit dependencies, modules have an explicit mechanism to define what they export. We can quickly read a module and know what it provides by looking at the return statement, instead of wondering what globals to access. define makes explicit that it is providing an interface to consumers.

define('math', ['dependencyA', 'dependencyB'], function(dependencyA, dependencyB) {
    // horrible things to local scope
    return {
            min: min,
            max: max,
            average: average

Avoid Script Tag Soup

<script src="scripts/utils.js">
<script src="scripts/numbers.js">
<script src="scripts/common.js">
<script src="scripts/formatting.js">
<script src="scripts/thing.js">
<script src="scripts/other.js">
<script src="scripts/site.js">

Did I type the path correctly? Are they ordered properly? Did someone change the order for a reason? Did they leave a comment, is it still applicable? What if I need to refactor one of them and change its position in the list?

With requirejs we can simply work on the dependency lists alone:

define('utils', [], function(){

define('numbers', [], function(){

define('common', ['utils', 'numbers'], function(){

define('formatting', [], function(){

define('thing', ['formatting'], function(){


This makes the dependencies explicit as we've shown above and doesn't hide meaning in an ordered list of script tags that are likely copy/pasted every time someone needs to load a set of dependencies, because who is going to manage this list and limit it to only the pieces they need, in every view of every application?

Confidence in Refactoring

Unlike in static typed languages, I can't just build to see if I messed up a dependency.

If dependency management is automatic, and we have an explicit, consistent specification of what interface we export from a module, and we use a function scope to organize our locals, it becomes very easy to make changes within a module, to split modules in parts etc. Our feeble human minds can focus on one module, but have a very difficult time taking into consideration the entire scope of the application. It's not that you can't practice this with function scopes alone, but it becomes a requirement with requirejs.

Shines a Light on Circular Dependencies and Intent

It's very easy to create circular dependencies in javascript, refactoring non module code to module code lets those issues bubble up to the dependency list and makes them apparent. It also helps other developers see how modules were intended to be used together, so they don't make assumptions and violate internal dependencies. You simply cannot see this stuff without a modular approach.

Simplified Testing

This falls back to script tag soup. When we setup tests we have to worry about loading scripts, even if it's just the module we are testing. We have three choices, take your pick:

  • Copy/paste a shared list between test fixtures, suffering testing speed and potentially breaking tests when updating this list.
  • Manually create this list for each test fixture, by manually scanning for dependencies, see above.
  • Use requirejs and forget about it

Simplifies Sharing Code

We have lots of handy JS we create, but sometimes we don't share it because it's too difficult to know what it needs. With requirejs, it's easy to see what needs to go with a piece of code, to use it elsewhere.

Works Client Side

Mobile and other solutions don't always end up using a server side technology and even if they do, it varies, so a module framework on the client is a huge benefit. Especially for organizing complex mobile applications.

Optimized Build

If desired, you can combine and minify your modules into one script for an optimized experience. The great part is you can use requirejs in dev without this and only add it as a deploy step, thus alleviating the need to build every time you make a change in dev.

Other benefits

  • Only load what you need, on demand and asynchronously!
  • Lazy loaded scripts
  • Although something is coming in ES harmony

    unless someone can get Microsoft to adopt rapid IE updates, even for old IEs, AMD will be around for a long time - James Burke

  • Consistent approach to mocking modules if testing via stubbing.

Articles against modules

Articles supporting modules

comments powered by Disqus