Using Local Modules With a Cross-Domain Dojo Build

Lately, I have been using Dojo from a CDN as much as possible. There are several reasons to use a cross-domain build of Dojo that are listed here:

  1. You get more connections in MSIE, since you can load from another domain. Faster loading.
  2. You get increased cacheability/startup if many of your applications use the same installation.
  3. Resource loading does not block the rest of the page from filling in as with Dojo’s normal, synchronous loading.
  4. With a local install, your ISP may otherwise charge you for all of those Dojo bits that you are serving.

The one problem with using a CDN is that you don’t have control over the build, which means you can’t build custom code into it. Building custom code into a build is what most people do with builds, so it would seem you can’t develop code using Dojo’s module system against a CDN. This couldn’t be farther from the truth.

In this post, we’re going to be using Dojo from Google’s CDN. This method can also be used against a custom cross-domain build. It may not seem like that would be very useful, but you may need to develop a new custom module against your build and don’t want to rebuild to test each change you make. Let’s look at the source:

xdlocal.html

<!DOCTYPE HTML>
<html>
<head>
	<title>XDomain Build With Local Modules</title>
	<style type="text/css">
		@import "https://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dijit/themes/tundra/tundra.css";
	</style>
	<script type="text/javascript">
		var djConfig = {
			isDebug: true,
			parseOnLoad: true,
			baseUrl: './',
			modulePaths: {
				'my': 'my',
				'dojo': 'https://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dojo',
				'dijit': 'https://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dijit',
				'dojox': 'https://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dojox'
			}
		};
	</script>
	<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dojo/dojo.xd.js"></script>
	<script type="text/javascript">
		dojo.require("my.Foo");
	</script>
</head>
<body class="tundra">
	<button dojoType="my.Foo">
		This is a "my.Foo" button.
	</button>
</body>
</html>

my/Foo.js

dojo.provide("my.Foo");

dojo.require("dijit.form.Button");

dojo.declare("my.Foo", dijit.form.Button, {
	onClick: function(){
		alert('Button clicked!!');
	}
});

I have also provided a live example as well to show it working. You can grab the source files in a tarball or zip file as well so you can play around with it.

The key part here is in the HTML file:

<script type="text/javascript">
	var djConfig = {
		isDebug: true,
		parseOnLoad: true,
		baseUrl: './',
		modulePaths: {
			'my': 'my',
			'dojo': 'https://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dojo',
			'dijit': 'https://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dijit',
			'dojox': 'https://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dojox'
		}
	};
</script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dojo/dojo.xd.js"></script>

djConfig is used to configure Dojo upon loading. The modulePaths object tells the loader where to find the modules relative to baseUrl and dojo, dijit, and dojox are set to point to the https URL for their resources so as not to get the “mixed content” error (the CDN build has http hard-coded because it was written during a time when https was not forced). The main thing to remember is that baseUrl must end in a /. Given this information, we can deduce that I am telling Dojo that the my modules can be found at https://www.reigndropsfall.net/demos/xdlocal/my/.

As you can see from this simple example, Dojo’s module system is very versatile. Not only can you host a build, host a custom build, host a cross-domain build, or use a CDN, but you can combine cross-domain builds with local modules which can save time and bandwidth costs.

UPDATE (11/18/2019): I have updated the example code and blog snippets to use https for the CDN resources as well as adding an explanation for why it’s needed.