MontageJS Bootstrapping
Note: “mopped” refers to
mop
, the Montage Optimizer
MontageJS calls exports.initMontage
after setting up some variables, which in turn calls getPlatform
, which returns an object with platform-specific functions (currently the browser and node.js are supported).
Browser
Development mode, i.e. non-optimized & un-mopped
platform.bootstrap
platform.bootstrap
is called with a callback to use when the initial bootstraping has finished. This kicks off the browser process. The parameters are retrieved from the data-
attributes of the script tag that loads montage.js
. A “resolve” function is also created that will return an absolute path from a given relative path, using the location of the document as the base. This is implemented by using <base>
and <a>
elements, and using the interaction of these elements in the browser to do the actual resolution.
Next we add a listener for DOMContentLoaded
, which will call callbackIfReady
when done.
Montage needs 3 files for further bootstrapping:
require.js
andbrowser.js
fromMr
to set up theCommonJS
module system in the browserq.js
- add support for promises
These are loaded by injecting script tags. We know when they are loaded because each of the files call a global bootstrap
function with their id and a function that returns their exports when ready. Mopped: If the package is Mopped then these files will be available in the bootstrapping bundle, and so no script tags are injected.
The global bootstrap
function keeps track of the 3 files and once all three have loaded calls the allModulesLoaded
function.
allModulesLoaded
uses a miniature require
implementation called bootRequire
to set up the promise and require/browser modules. Finally it calls callbackIfReady
.
callbackIfReady
checks that both the DOM
and the modules are loaded, and if so calls the callback given to this function.
Callback
First we set up the config object to load the Montage package. This involves setting up the loader that lets the us load .reel
files directly (e.g. require("montage/ui/text.reel")
), and compilers that attach Montage metadata to the exports of any loaded module (SerializationCompiler
) and export the HTML of loaded HTML files as content
(TemplateCompiler
).
If mopped, bundles are loaded at this point.
We then use Require
to load the Montage package. Once this promise has completed we have the require function for Montage, montageRequire
. We use this to load the Q (Promise) package so that we have complete information about the Promise package. We then insert the already loaded promise module into it, so that it isn’t requested again. We set up the linter, to give us informative errors when there’s a syntax error in a loaded file.
At this point there is code to handle controlling the Montage bootstrapper from a remote frame, for example for testing. This won’t be covered here.
If there was a data-auto-package
attribute we create inject a fake package description so that a package.json is not needed, otherwise we check if location is a json file (set through a data-package
attribute) and if so inject it directly. Finally, we load the application package.
Once this is complete we have the montageRequire
and the applicationRequire
and we use these to finish initializing Montage in initMontage
initMontage
Here we load the last of Montage’s essential dependencies and once they have completed we configure the application. This involves setting up the stack trace length (set to 0 for optimization), event manager and calling montageWillLoad
, again for testing.
Next we check to see if the package.json
specified an application prototype to use, otherwise we use “core/application”. Once this is loaded will call _load
on the application object which in the default implementation loads the Montage component and template modules, and causes any serialization in this HTML page to be parsed.
Finally, we check if a data-module
attribute was given and if so load this module.
The bootstrapping is complete. The serialization has created components for the user to interact with, or the loaded module is doing its thing.
Production mode, i.e. optimized & mopped
When Mopped the bootstrapping bundle defines a global BUNDLE
array, which contains a list of bundle filenames to load.
platform.bootstrap
As the normal bootstrap, except the 3 bootstrapping modules needed will be available in the bootstrapping bundle, and so no script tags are injected.
Callback
Before loading the Montage package the BUNDLE
variable is checked. If it exists then a script tag is injected for each of the filenames in the array. Each bundle calls a global bundleLoaded
function with its name. A preloaded
promise is added to the config object that is resolved once all of the bundles have loaded. Mr waits on this promise before proceeding, which means that the Montage package is not loaded until all the bundles have loaded.
This is where the differences in un-mopped and mopped bootstrapping end.
Node.js
Montage currently does not support Node.js.