How to build Dojo into a single file, given a list of dependencies?

Rogach picture Rogach · Dec 13, 2012 · Viewed 8.9k times · Source

I have a simple Dojo application, that does only one require call, loading all the dependencies. The trouble is, while it is extremely simple, it still ends up loading ~100 files from server. I tried to solve that problem using Dojo build system, but seems I don't have a deep enough understanding.

So my question is - given a list of dependencies, like the following:

["dojo/parser",
 "dijit/registry",
 "dojo/dom",
 "dojo/on",
 "dojo/query",
 "dojo/dom-class",
 "dojo/request",
 "dijit/form/ValidationTextBox", 
 "dijit/form/Select",
 "dijit/form/NumberSpinner",
 "dijit/form/CheckBox",
 "dijit/layout/ContentPane",
 "dijit/Dialog",
 "dojo/NodeList-traverse",
 "dojo/domReady"]

how do I set up the build to create a single-file (or several-file, just not 100-file) dojo file?

Answer

voithos picture voithos · Dec 13, 2012

If you're using Dojo's require() loader, there are build tools that you can use to combine files and minify. According to the site, the build tools aren't included in an official release, so you'll have to get them from the development version (specifically, look in the buildscripts directory).

The Dojo documentation contains some info on its build system that you may also find useful.

As a proof of concept, here are the steps I took:

  1. Go to the download page, and download the Source Dojo Toolkit SDK (it's the only one that contains the util scripts needed for a build).

  2. Extract to a location (for the sake of this post, let's say it's /opt/dojo-toolkit).

  3. From the Dojo toolkit directory (i.e. /opt/dojo-toolkit), run the build util: ./util/buildscripts/build.sh action=release htmlFiles=/path/to/my/index.html (careful, this slowed my 5-year-old dual-core to a crawl)

Example of index.html (this one is exactly inside the dojo-toolkit directory):

...
<head>
    <script src="dojo/dojo.js"></script>
    <script>
    dojo.require("my.test");
    </script>
</head>
...

The require() call looks for nested modules (I couldn't get it to work with a top-level module), so in this case, I've got a my directory inside of dojo-toolkit which contains a test.js file. That file is the main "bootstrap" file which loads in all of the dependencies. I just put random require() calls in mine:

dojo.require('dijit.ProgressBar');
dojo.require('dijit.Tree');

And that should do it. Basically, running the build utility against your HTML file (the one that contains the reference to dojo.js) makes sure that all of the dependencies are found, starting from the top.

Note: the build system create a release directory with the built output, but it looks a little misleading at first - it appears to have minified each individual file, but if you look at your actual bootstrap file (my/test.js, in this case), it will be a combined, minified file with (I presume) everything you need to run your app.


Otherwise, if you're using AMD style require()'s (as in require.js), you can use its optimization tool. According to the site, it will:

  1. Combine all dependent files (including require.js itself) into a single file. It analyzes the require() call to figure out which files it needs to combine.

  2. Minify your JavaScript using either UglifyJS (default) or Closure Compiler.