Login Register

The Package System and Custom Builds

A Dojo custom build speeds performance by doing the following:

  1. First, it groups together modules into layers. A layer, which is one big .js file, loads faster than the individual .js modules that comprise it
  2. Second, it interns external non-JavaScript files. This is most important for Dijit templates, which are kept in a separate HTML file. Interning pulls the entire file in and assigns it to a string.
  3. Third, it smooshes the layer down with ShrinkSafe. ShrinkSafe removes unneeded whitepsace and comments, and compacts variable names down to smaller ones. This file downloads and parses faster than the original.
  4. Finally, it copies all non-layered scripts to the appropriate places. While this doesn't speed anything up, it ensures that all Dojo modules can be loaded, even if not present in a layer. If you use a particular module only once or twice, keeping it out of the layers makes those layers load faster.

The catch? You have to designate the modules in each layer with a profile, which is something like a Makefile or Ant script. But that's not too hard if you know your app well.

So the input of the build system is the Dojo source tree, plus any source trees for custom stuff you wish to include ... plus the profile. The output is a Dojo distribution tree which you can copy to your web server. Sweet!

Prerequisites

You need the following installed on your computer to run Dojo's build system:

Creating a Custom Profile

In the util/buildscripts/profiles directory, you will create a profile build file called foo.profile.js like this:

dependencies ={
    layers:  [
        {
        name: "mydojo.js",
        dependencies: [
            "dijit.Button",
            "dojox.wire.Wire",
            "dojox.wire.XmlWire",
            "explosive.space.Modulator"
        ]
        }
    ],
    prefixes: [
        [ "dijit", "../dijit" ],
        [ "dojox", "../dojox" ],
        [ "explosive", "../../explosive" ]
    ]
};

The dependencies section within the layer lists all the modules you call directly. Any referenced modules will also be included, so you don't have to trace back the dependency tree. Also, Dojo base modules are an implicit dependency, so you don't need to list things like "dojo.query". (Dojo core modules, however, do need to be listed.)

The modules for that layer are gathered together to make the "layer" file, in our example: "mydojo.js". Then you just load this layer file in your pages with a SCRIPT tag. Easy!

The prefixes section list any modules that need inclusion. Note our "explosive" module, which is located away from the Dojo tree. You need to list these if you use them, even if you don't want any modules from it in your layer file.

For the 1.0+: If you choose to optimize the JS files in a prefix directory (via the optimize= build parameter), you can choose to have a custom copyright text prepended to the optimized file. To do this, specify the path to a file tha contains the copyright info as the third array item in the prefixes array. For instance:

prefixes: [
    [ "explosive", "../../explosive", "../../explosive/copyright.txt"]
]

If no copyright is specified in this optimize case, then by default, the dojo copyright will be used.

Running The Build

After specifying a profile file as shown above that statically specifies the resources you want to include, and saving it as /buildscripts/profiles/foo.profile.js, you run the Rhino interpreter on it and specify the profile name as a parameter. For example, from the buildscripts directory:

$ cd util/buildscripts
$ build.sh profile=foo action=release

On Windows PC's, substitute build.bat for build.sh. For both platforms, you may also specify additional build options. Run build.sh to see a list of all supported options. Here is a sample of the supported options:

profile The name of the profile to use for the build. It must be the first part of the profile file name in the profiles/ directory. For instance, to use base.profile.js, specify profile=base. Default: base
profileFile A file path to the the profile file. Use this if your profile is outside of the profiles directory. Do not specify the "profile" build option if you use "profileFile" Default: "",
action The build action(s) to run. Can be a comma-separated list, like action=clean,release. The possible build actions are: clean, release Default: "help",
version The build will be stamped with this version string Default: "0.0.0.dev",
localeList The set of locales to use when flattening i18n bundles Default: "en-gb,en-us,de-de,es-es,fr-fr,it-it,pt-br,ko-kr,zh-tw,zh-cn,ja-jp",
releaseName The name of the release. A directory inside 'releaseDir' will be created with this name Default: "dojo",
releaseDir The top level release directory where builds end up. The 'releaseName' directories will be placed inside this directory Default: "../../release/",
loader The type of dojo loader to use. "default" or "xdomain" are acceptable values." defaultValue: "default",
internStrings Turn on or off widget template/dojo.uri.cache() file interning Default: true,
optimize Specifies how to optimize module files. If "comments" is specified, then code comments are stripped. If "shrinksafe" is specified, then the Dojo compressor will be used on the files, and line returns will be removed. If "shrinksafe.keepLines" is specified, then the Dojo compressor will be used on the files, and line returns will be preserved. If "packer" is specified, Then Dean Edwards' Packer will be used Default: "",
layerOptimize Specifies how to optimize the layer files. If "comments" is specified, then code comments are stripped. If "shrinksafe" is specified, then the Dojo compressor will be used on the files, and line returns will be removed. If "shrinksafe.keepLines" is specified, then the Dojo compressor will be used on the layer files, and line returns will be preserved. If "packer" is specified, Then Dean Edwards' Packer will be used Default: "shrinksafe",
copyTests Turn on or off copying of test files Default: true,
log Sets the logging verbosity. See jslib/logger.js for possible integer values Default: logger.TRACE,
xdDojoPath If the loader=xdomain build option is used, then the value of this option will be used for the path to Dojo modules. The dijit and dojox paths will be assumed to be sibilings of this path. The xdDojoPath should end in '/dojo' Default: "",

Cross Domain (XDomain) Builds

Doing an xdomain build allows you to load Dojo and your custom modules from another domain. The benefits to doing this are listed in the 0.4 Book page about Cross Domain Resource Loading.

To do an xdomain build:

$ cd util/buildscripts
$ build.sh profile=foo loader=xdomain xdDojoPath=http://my.server.com/path/to/buildoutputdir action=release

xdDojoPath is optional. It just burns in the location of dojo, dijit and dojox into the built dojo.js. If you do not specify that option, then you will need to use djConfig.modulePaths/dojo.registerModulePath() in your HTML page to set the xdomain locations for dojo, dijit and dojox. For your own custom modules, you will have to set djConfig.modulePaths/dojo.registerModulePath() even if you us the xdDojoPath build option.

For 0.9+ there is a bug about loading dojox.gfx with an xdomain build.. If you want to use dojox.gfx with an xdomain build, there are some workarounds until the bug gets fixed:

  1. Include dojox/gfx.js directly in your page with a script tag in the HTML source, after the dojo.js script tag (do not use gfx.xd.js, use gfx.js).
  2. Include dojox.gfx in a layer file that you load via a script tag in the HTML source (load the .js layer file, not the .xd.js layer file).

Bugs / Pitfalls with custom builds

You really do have to do your own custom packaging of dojo in order to get the snappy performance we all want. Generally, what we have done is this:

1.) Added a dojo-build directory to our project, which holds a src version of dojo untarred.
2.) Have two header files, one for dojo-dev, and one for dojo-prod. This allows us to have the standard dojo-release for our development purposes (this file holds the link lines, djconfig, etc) and one for production, which just links to our custom dojo base file, and our custom dijit file. Our build process scrapes out the dojo.require's from our tpl templates. This way, you only have two requests for all of dojo, and your own widgetry. We also scrape out the addModule line, as that is not needed in production.
3.) The profile file as shown above lists all of the dijits , and our own widgets, that are called DIRECTLY. This is important to manage, and should be thought about whenever you add / remove a dijit or custom widget from your app. The prefixes are just dijit, and our own module. Try to embed all of your requires for each custom widget within it's Widget.js file.

For php folk, the concept of a build is pretty foreign. But eventually, as your app gets bigger, you need something like ant or phing in order to build, and deploy, your app. The dojo build process just hooks right into whatever build script you use. We fire the command line build.sh with parameters telling it where our profile file, and deployment dir (right in our js dir) should be.

Like most people, I took the tundra theme, and used it as a base for our own theme. I wanted the theme to be completely seperate from the dojo directory, in our css dir. At the top of tundra.css, you will see a relative link to the base dijit.css file. This bit us hard after our custom build. If you move your theme dir outside the dojo area, a relative link will break in a custom build (since the dojo-1.0.1 dir is not present in the production dist), but firebug cant catch that the dijit.css core file was 404. All dijits were messed up until we changed this. Our production dojo_head.tpl file links to the production custom build's dijit.css, and then our own theme css. e.g.:

@import url("js/dojo-release/dojo/dijit/themes/dijit.css");
@import url("css/themes/gq/gqdojo.css");


How to use a custom build

I've seen a lot of discussion on the boards about how one should use the custom build after you've created a layer file with additional classes compiled in. For a local Dojo build (not XDomain) as listed above, I think the correct HTML code to reference the layers is:

<script type="text/javascript" src="/js/release/dojo/dojo/dojo.js"></script>
<script type="text/javascript" src="/js/release/dojo/dojo/mydojo.js"></script>

Is this correct? The important thing to note is that you have to reference both the dojo.js and mydojo.js files, I think.

[mis-post]

[deleted]

Build Profile Parameter Descriptions Table

In order to try and fully understand the dojo build profile parameters, I have attempted to describe them in the following table. If there are errors or omissions in what I have posted, please let me know and I will be happy to correct them.

For source code at version 1.0.2, this table assumes a minimal build command of the form:

./build.sh profile="yourProfileFilenameHere" action="release" version="1.0.2"

where you run the command from the path:

/dojo-release-1.0.2-src/util/buildscripts

Build Parameter		Function		Optional			If not provided, then:

dependencies		Container for layers	N if layers are provided.	Generates dojo.js base library.

layers			list of dojo libraries	N if dependencies are provided.	N/A
			to be built, where 
			each library is 
			stored in a separate 
			file			

name			path where layer is	N if dependencies are provided.	N/A
			to be stored. This
			path is relative to 
			the release/dojo/dojo 
			directory. Both a
			compressed (<name>.js) 
			and an uncompressed 
			(<name>.js.uncompressed.js) 
			module file will be 
			built. 

resourceName		string defining a	Y				No dojo.provide is included
			library; causes a 					in generated build file.
			dojo.provide to be 
			placed in the generated 
			build file where 
			resourceName is the 
			name you choose to 
			define your custom 
			built library. This
			name defines the
			namespace for the
			module to be 
			generated in the 
			given layer. (broken
			in versions 0.9 to 
			1.0.2 - see bug 5688)
							
layerDependencies	list of prebuilt dojo	Y				Assumes a dependency on dojo.js. 
			or custom libraries 					Generates dojo.js base library
			that libraries to be 					by default and copies it into the 
			generated depend upon					release directory.
						
dependencies		list of dojo widgets 	Y				No library beyond base libraries 
			to be built (baked) 					will be generated.
			into the generated 
			layer file defined by 
			the “name” parameter; 
			the dependencies are 
			those widgets that you 
			will request in your 
			web page(s) through 
			dojo.require statements

prefixes		list of dojo or custom 	Y				Modules are not copied to 
			directory paths where 					release directory.
			individual dojo modules 
			(for example individual 
			widget source files) 
			are stored. A module
			may reference other
			namespaces through
			dojo.require() 
			statements. The contents 
			of these directories are 
			copied to the release 
			directory during the 
			build sans any modules 
			included in the generated 
			base libraries or 
			libraries defined by the 
			“name” parameter

Path name is incorrect in 1.0.2

Hi.
Under the header "Creating a Custom Profile", the path name src/buildscripts/profiles should read utils/buildscripts/profiles.

Fixed

I've updated the page. Thanks :)