This tutorial is for Dojo 1.6 and may be out of date.

Up to date tutorials are available.

Using Custom Modules with a CDN

There are a number of benefits to loading Dojo from a CDN, but using it and custom modules can be a little confusing at first. This tutorial will demonstrate how easily that can be done.

Introduction

Dojo modules are hosted on a few Content Delivery Networks (or CDNs) to provide high-speed access to the Dojo resources for your web applications. Using CDNs can result in greatly improved application performance; they are faster and offer more potential for cached results, more simultaneous connections to be downloading from, and other performance-based improvements. CDNs achieve improved performance by directing requests to local servers; it's an easy way to improve performance of initial loads and benefit your web application. However, using Dojo from a CDN while also using custom modules isn't a terribly intuitive process at first.

The applications that can benefit from CDN usage are public applications (accessed from a wide range of geographic areas by users with access to the Internet) that do not use a large number of Dojo (or Dijit or Dojox) modules. When a large number of modules are needed, the number of HTTP requests that are required may be excessively slow, and using a locally served build will probably be a better option. However, for the many applications in which CDN is the preferred way to load Dojo modules, we may still need to load our own custom modules from our own server.

Loading our Modules

For example, our application may have a custom widget that we want to use. To see how to use CDN with our modules, let's start with a simple HTML page:

<html>
  <head>
  </head>
  <body>
  </body>
</html>

Now we will load dojo.js from a CDN. In this example we use Google's CDN, so we will add this script tag:

<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js"
	type="text/javascript">
</script>

This will load Dojo base and we can immediately start using the base functionality. We can make dojo.require calls to load other modules. However, one thing to be aware of is that there are a few modules that require access to a same-origin blank HTML page. Let's make sure we have a blank.html on our server, and expand our script tag:

<script data-dojo-config="
			dojoBlankHtmlUrl:'/blank.html'"
		src="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js"
		type="text/javascript">
</script>

Now we can setup a module space for modules served from our server. For our application, we will configure the Dojo loader so that all non-Dojo modules in the custom.* namespace come from our server, in the js/custom folder. We configure a base URL for our JS modules and then define the module path for the "custom" namespace relative to that:

<script data-dojo-config="
			dojoBlankHtmlUrl:'/blank.html',
			baseUrl: 'js/',
			modulePaths: {custom: 'custom'}"
		src="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js"
		type="text/javascript">
</script>

Here we used the "data-dojo-config" which is new in 1.6. For older versions of Dojo, you need to use the "djConfig" attribute to configure Dojo.

Let's also add the Claro theme from CDN so that we can use Dijit widgets with the prebuilt Claro styling. We add a stylesheet link that points to the Claro theme:

<link rel="stylesheet"
	href="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dijit/themes/claro/claro.css" />

Make sure you remember to set the claro class on the body (or wherever you want the theme contained to):

<body class="claro">...

Our page should now look like:

<html>
  <head>
    <link rel="stylesheet"
		href="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dijit/themes/claro/claro.css" />
    <script data-dojo-config="
			dojoBlankHtmlUrl:'/blank.html',
			baseUrl: 'js/',
			modulePaths: {custom: 'custom'}"
		src="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js"
		type="text/javascript">
    </script>
  </head>
  <body class="claro">
  </body>
</html>

Now we create a script block that will require our module:

<script>
dojo.require("custom.Hello");
</script>

Once the module is loaded, we can interact with the class that it declares. One of the key differences between same-origin module loading and CDN loading is that dojo.require() calls operate asynchronously at the top level. This means that we can't simply call custom.Hello in the next statement after the dojo.require() call, but we must register a callback for when the modules are ready. We use the dojo.ready() function to provide a callback. This will ensure that everything is loaded before continuing execution:

// indicate we want custom.Hello to be loaded
dojo.require("custom.Hello");
// wait for everything to load
dojo.ready(function(){
	// now we have everything loaded and we are ready to go
	// let's instantiate a Hello World Dialog from our class:
	customWidget = new custom.Hello({
		content: "Hello World!"
	}, "hello"); // make sure you have an element with the id of "hello"
	// and show it
	customWidget.show();
});

The last piece is to create the custom.Hello module. We put the Hello.js file in the js/custom/ folder. In our demo, it is a simple extension of dijit.Dialog that assigns a default title to the Dialog:

dojo.provide("custom.Hello");
// The dijit.Dialog module is going to be retrieved from CDN:
dojo.require("dijit.Dialog");
// declare our custom class
dojo.declare("custom.Hello", [dijit.Dialog], {
	// assign a title for the Dialog
	title: "Hi"
});
View Demo

Our final page should look like:

<html>
  <head>
    <link rel="stylesheet"
		href="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dijit/themes/claro/claro.css" />
    <script data-dojo-config="
			dojoBlankHtmlUrl:'/blank.html',
			baseUrl: 'js/',
			modulePaths: {custom: 'custom'}"
		src="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js"
		type="text/javascript">
    </script>
	<script>
		// indicate we want custom.Hello to be loaded
		dojo.require("custom.Hello");
		// wait for everything to load
		dojo.ready(function(){
			// now we have everything loaded and we are ready to go
			// let's instantiate a Hello World Dialog from our class:
			customWidget = new custom.Hello({
				content: "Hello World!"
			}, "hello"); // make sure you have an element with the id of "hello"
			// and show it
			customWidget.show();
		});
	</script>
  </head>
  <body class="claro">
	<div id="hello"></div>
  </body>
</html>

Summary

CDN-based loading provides numerous benefits including geographically close resource transfers, increased/shared caching with other sites that use the same modules, fast asynchronous loading, and less load on your own servers. Dojo provides excellent support for integration of CDN loading with loading of our your own custom modules from our server. We can use baseUrl and modulePaths configuration settings to point to your custom module directories and ensure that we use dojo.ready() to wait for the modules to be loaded.

Links