Building a Library with RequireJS

Emre Guneyler

RequireJS is an AMD module loader for browsers that can load your script and CSS files asynchronously. You no longer have to deal with the order of script files inside an individual file (e.g. index.html). Instead, you just wrap your code inside module definitions and RequireJS will take care of the dependencies, making your code more structured and well organized. It also has an optimizer tool that uglifies and concatenates the files for production use.

The official site provides extensive documentation about its API, and there are many example repositories to help you. But it has a lot of configuration and it is tricky at first to get started with RequireJS.

In this article we will learn how to use RequireJS by building a library using AMD modules, optimizing it and exporting it as a standalone module using the RequireJS optimizer. Later we will use RequireJS to build an application and consume our library.

This tutorial assumes some familiarity with RequireJS. If you are looking for a primer, check out: Understanding RequireJS for Effective JavaScript Module Loading.

Installing RequireJS

RequireJS is available through bower:

bower install requirejs --save

or you can grab the files on github.

There is also a Grunt-based Yeoman generator for RequireJS projects.

Defining an AMD module

We will wrap our code inside define(), and that will make it an AMD module.

File: mylib.js

define(['jquery'], function($) {
    // $ is jquery now.

    return 'mylib';

That’s it. Note that define() takes an optional first argument of a dependency array, in this case it is ['jquery']. It’s the dependency list for this module. All the modules inside the array will be loaded before this module. When this module is executed, the arguments are the corresponding modules in the dependency array.

So in this case jQuery will be loaded first, then passed into the function as parameter $, then we can safely use it inside our module. Finally our module returns a string. The return value is what gets passed to the function parameter when this module is required.

Requiring Other Modules

Let’s see how this works by defining a second module and require our first module mylib.js.

File: main.js

define(['jquery', 'mylib'], function($, mylib) {
    // $ is jquery as usual
    // mylib is the string `mylib` because that's the return value
    // from the first module

    return {
        version: '0.0.1, jQuery version: ' + $.fn.jquery,
        mylibString: mylib

You can require as many dependencies as you like inside the dependency array, and all the modules will be available through the function parameters in the same order. In this second module we required the jquery and mylib modules, and simply returned an object, exposing some variables. The user of this library will use this object as your library.

Configuring the RequireJS Optimizer: r.js

You might be wondering, how does RequireJS know what file to load only by looking at the string in dependency array? In our case we provided jquery and mylib as strings, and RequireJS knows where those modules are. mylib is simple enough, it’s mylib.js with .js omitted.

How about jquery? That’s where RequireJS config is used. You can provide extensive configuration through a RequireJS config. There are two ways to provide this config, since we are using the RequireJS optimizer, I will show you the r.js way. r.js is the RequireJS optimizer.

We will provide r.js with a config, and it will optimize all the modules into a single file. The configuration that we provide will make r.js build the modules as a standalone global library that can be used both as an AMD module or as a global export in the browser.

r.js can be run via command line or as a Node module. There is also a Grunt task grunt-requirejs for running the optimizer.

That being said, let’s see what our configuration looks like:

File: tools/build.js

  "baseUrl": "../lib",
  "paths": {
    "mylib": "../main"
  "include": ["../tools/almond", "main"],
  "exclude": ["jquery"],
  "out": "../dist/mylib.js"
  "wrap": {
    "startFile": "wrap.start",
    "endFile": "wrap.end"

The configuration file is really the meat of RequireJS. Once you understand how these parameters work, you can use RequireJS like a pro.

You can do different things, and tweak your project builds with the configuration file. To learn more about configuration and RequireJS in general I recommend referencing the docs and the wiki. There is also an example configuration file, that demonstrates how to use the build system, so make sure to reference that as well.

Finally we actually run the optimizer. As I said before, you can run it via command line, or Node, as well as a Grunt task. See the r.js README to learn how to run the optimizer in different environments.

node tools/r.js -o tools/build.js

This will generate the build file in dist/mylib.js


Next, let’s see what the parameters actually mean.

baseUrl – The root path for all module lookups.

paths – Path mappings for module names that are relative to baseUrl.

In our example, “mylib” maps to “../main”, that is relative to baseUrl, so when we require “mylib” it loads the file “../lib/../mylib/main.js”.
Notice we appended baseUrl, then the paths setting, than the module name followed by a .js suffix. That’s where you specify how modules are mapped to files such as jquery and mylib.

include – The modules we want to include in the optimization process. The dependencies that are required by the included modules are included implicitly. In our case, main module depends on mylib and jquery that will get included as well, so no need to include it explicitly. We also include almond that I will mention later.

exclude – The modules we want to exclude from the optimization process. In our case we exclude jquery. The consumers of the built library will provide a jQuery library. We will see that when we consume our library later.

out – The name of the optimized output file.

wrap – Wraps the build bundle in a start and end text specified by wrap. The optimized output file looks like: wrap.start + included modules + wrap.end. wrap.start and wrap.end are the names of the files in which their contents get included in the output.


The built library does not include require.js in the file, but instead uses almond. almond is a small AMD API implementation, that will replace require.js.

Wrapping our Library

In the r.js config we wrapped our library with wrap.start and wrap.end files. We also included almond in our library, those will make our library standalone, so they can be used without RequireJS through browser globals or as an AMD module through requirejs.

File: wrap.start

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD.
    define(['jquery'], factory);
  } else {
    // Browser globals.
    root.mylib = factory(root.$);
}(this, function($) {

Our included modules main, mylib, and almond are here in the middle of wrap.start and wrap.end.

File: wrap.end

// Register in the values from the outer closure for common dependencies
  // as local almond modules
  define('jquery', function() {
    return $;

  // Use almond's special top level synchronous require to trigger factory
  // functions, get the final module, and export it as the public api.
  return require('mylib');

If the consumer uses an AMD loader, then the built file will ask for ‘jquery’ as AMD dependencies. If the consumer just uses browser globals, the library will grab the $ global variable and use it for jQuery dependency.

Using the Library with RequireJS

We are done with our library, now let’s actually use it by building a requirejs application.

File: app.js

define(['jquery', 'mylib'], function($, mylib) {
  // $ is jquery
  // mylib is mylib that is:
  // {
  //   version: 'version 0.0.1 jQuery version: xxx',
  //   mylib: 'mylib'
  // }

Nothing fancy here, it’s another module that requires jQuery and mylib. When a module is defined with define it is not immediately executed, that is its callback function (which is passed after the dependency array) is not executed right away. That means our application doesn’t start just by defining this module. Now let’s see how to configure RequireJS and actually execute this module that is our application.

Configuring RequireJS for the Browser

We will configure RequireJS and execute our app module in one file. There are different ways of doing this though.

File: common.js

  baseUrl: '../lib',
  paths: {
    'jquery': 'jquery/dist/jquery.min',
    'underscore': 'underscore/dist/underscore',
    'backbone': 'backbone/backbone',
    'mylib': 'mylib/dist/mylib',
    'app': '../app'
  shim: {
    'jquery': {
      exports: '$'
    'backbone': {
      deps: ['jquery', 'underscore'],
      exports: 'Backbone',
    'underscore': {
      exports: '_'

require(['app/app'], function(App) {
  // app module is available here
  // you can start your application now
  // this is immediately called because
  // we used `require` instead of `define`
  // to define this module.

The baseUrl and paths config are the same as before. The additional config value here is:

shim: Configures the dependencies and exports for traditional “browser globals” scripts that do not use define() to declare the dependencies and set a module value. For example, Backbone is not an AMD module, but it’s a browser global that exports Backbone into the global namespace that we’ve specified in the exports. In our example, the module also depends on jQuery and Underscore, so we specify that using deps. The scripts in the deps array are loaded before Backbone is loaded, and once loaded, the exports value is used as the module value.

Note that you can also use r.js in this application project as well, which will require a separate configuration. But don’t get confused by that. I won’t go into detail on how to do that, but it’s similar to what we did for our library. See the example build config for further reference.

require vs define

Later we use require to load a module and immediately execute it. Sometimes define and require can be confused as to which one is used when. define defines a module, but doesn’t execute it, require defines a module and executes it – that is, it loads and executes the dependent modules before executing itself. Often you will have one require as a main entry module that will depend on additional modules that are defined via define.

Loading the Scripts

Typically you include all your script files in your index.html. Now that we are using RequireJS, we only have to include RequireJS and specify our data-main, which is the entry point to our application. There are different ways of setting up the config options, or separating the main module used in index.html. You can find more information on that here.

<script data-main="scripts/common" src="scripts/lib/require/require.js"></script>


In this article we have built a library, and an application that uses that library with RequireJS. We learned how to configure the r.js optimizer, and how to configure RequireJS in the browser. Finally we learned how to use RequireJS to define and use AMD modules. That made our code well structured and organized.

I’ve used this example-libglobal repo in this tutorial for the first half (configuring the optimizer), and the second half is not that complicated, so you should be good to roll your own now.

The official RequireJS website is the ultimate documentation, but make sure to check out the example repos on github as well the example projects in that repo, which demonstrate the use of a RequireJS application.