Sunday, October 20, 2013

Module loading in dojo (1.9)

How Dojo locates a module

The official Dojo tutorials unfortunately contain many errors or omissions. So, I had to write down my findings from my experiment. When we request the Dojo loader to load a module with id, say, foo/bar, it will basically start the search from the "base URL". The base URL by default is the folder containing dojo.js. Then it will drill down the path using the module id. For example, if dojo.js is loaded like:

then the base URL will be http://www.abc.com/js/dojo-dist/dojo and therefore, in principle, the Dojo loader will drill down and try to load http://www.abc.com/js/dojo-dist/foo/bar.js file. However, because Dojo is distributed with the following folder structure, it will mean that you need to put your foo folder into the dojo folder (which contains the core files of Dojo):
 js
  |
  +-- dojo-dist
       |
       +-- dojo  <--- 1: the base URL by default
       |     |
       |     +-- dojo.js
       |     |
       |     +-- foo  <--- 2: drill into here
       |          |
       |          +-- bar.js
       |
       +-- dijit
       |
       +-- dojox
       |
       +-- util
This doesn't make sense. Therefore, Dojo by default assumes that your files are put into a folder that is a sibling of the folder pointed to by the base URL. That is, after locating the base URL, it will go back one level before drilling down using the module id:
 js
  |
  +-- dojo-dist  <--- 2: go back to here
       |
       +-- dojo  <--- 1: the base URL by default
       |      |
       |      +-- dojo.js
       +-- dijit
       |
       +-- dojox
       |
       +-- util
       |
       +-- foo  <--- 3: drill into here
            |
            +-- bar.js
To observe the effect of this "going back one level", you can set the tlmSiblingOfDojo ("top level module sibling of Dojo") option between true (default, go back) and false (don't go back):


Putting the foo folder as a sibling of the dojo folder is better (at least the foo folder is not mixed with the core Dojo files). You might interpret the dojo-dist folder containing all Dojo related files, i.e., files from the Dojo Foundation and files created by you that use Dojo.

Putting your own files outside the Dojo folder structure

However, you may not like the above folder structure and decide to put your own files outside the dojo-dist folder, like:
 js
  |
  +-- dojo-dist
  |    |
  |    +-- dojo
  |    |     |
  |    |     +-- dojo.js
  |    +-- dijit
  |    |
  |    +-- dojox
  |    |
  |    +-- util
  |
  +-- foo
       |
       +-- bar.js
Then you must set the base URL yourself. You may set it to the dojo-dist folder and continue to rely on the default tlmSiblingOfDojo to go back to the js folder, before it drills down to the foo folder:
 js  <--- 2: let it go back to here
  |
  +-- dojo-dist  <--- 1: set the base URL to here
  |    |
  |    +-- dojo
  |    |     |
  |    |     +-- dojo.js
  |    +-- dijit
  |    |
  |    +-- dojox
  |    |
  |    +-- util
  |
  +-- foo  <--- 3: drill into here
       |
       +-- bar.js
Obviously, when setting the base URL yourself, it no longer has the meaning of "the folder containing dojo.js" and thus the tlmSiblingOfDojo option is really meaningless; it only means whether it should go back one level. The code is like:


As going back one level in this case is really confusing, it is better to just turn that off and set the base URL to the js folder:
 js  <--- 1: set the base URL to here and do NOT go back one level
  |
  +-- dojo-dist
  |    |
  |    +-- dojo
  |    |     |
  |    |     +-- dojo.js
  |    +-- dijit
  |    |
  |    +-- dojox
  |    |
  |    +-- util
  |
  +-- foo  <--- 2: drill into here
       |
       +-- bar.js
The code is like:


Instead of a full URL, the base URL can also be set as an absolute path (on the same host with the same protocol used to access the enclosing HTML file) or a relative path (to the enclosing HTML file). For example, If the enclosing HTML file is a sibling of the js folder, then it is better to use a relative path:


A more flexible location mechanism

Putting the modules as direct children of the base URL is fine, but may be too limiting. If you would like to have complete control over where to put each module, you can make use of the concept of a "package". A package can be considered a location with a name. For example, you can define a package named "foo" whose location is http://www.abc.com/js/myapp, then when you're trying to load the foo/bar/baz module, Dojo will note that the module id (foo/bar/baz) starts with foo, so it is in the foo package and thus it will go to http://www.abc.com/js/myapp first and then drill down to the bar folder and load baz.js:



Instead of using a full URL as the package location, it is possible to use an absolute path (use the same protocol and host as the base URL) or a relative path (to the base URL). Note that when locating a module through through the package method, which is much more flexible than the "assuming everything is a sibling of dojo", the tlmSiblingOfDojo is NOT used at all. That is, Dojo will locate the base URL, never go back one level, combine it with the package location (absolute or relative path) to determine the full URL for the package. Here is an example of a relative path:


Here is an example of an absolute path:


Of course, it is possible to define multiple packages:


No comments:

Post a Comment