Bundling for deployment
A common setup when using JS.Class for web development is to include the
package loader and your package manifest using script tags, then using
JS.require() to load components as you need them.
<script type="text/javascript" src="/js.class/loader.js"></script>
<script type="text/javascript" src="/manifest.js"></script>
<script type="text/javascript">
JS.require('Application', function() {
// ...
});
</script>
In this case manifest.js might contain:
JS.Packages(function() { with(this) {
file('https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js')
.provides('jQuery');
file('/app.js')
.provides('Application')
.requires('jQuery');
}});
This setup makes it really easy to load the JavaScript modules you need during development, but in production you often benefit from bundling all the JavaScript for a page into a single file.
jsbuild
jsbuild is a command-line program that’s written in Node. It takes as input
your package manifest and a list of modules you want to use, and will output
a single JavaScript file containing those modules and all their dependencies.
It expects to find your modules on the local filesystem and can also include
external scripts from the web.
To build a package, install JS.Class using npm:
npm install --global jsclass
Then run this command:
jsbuild --manifest MANIFEST --root ROOT [OPTIONS] module1 [module2 ...]
The options available are:
--manifest,-m: the path to your package manifest. If you only want to use modules from JS.Class itself, this is optional.--root,-r: the directory containing your application’s JavaScript files. Paths in the manifest are resolved relative to this directory.--external,-e: unless this option is passed, the build will skip files that come from external domains rather than the local filesystem.--no-packages,-P: if this is set, theJS.Packagessystem will not be included in the build. Including it means yourJS.require()calls will carry on working.--bundles,-b: optional path to bundle definition file (see ‘Organising bundles’ below).--output,-o: the type of output required, eithercode(default) orpaths. Usingcodemakesjsbuildoutput the combined source code, andpathsmakes it output the paths to the bundled files.--directory,-d: a directory to trim from paths output when using-o paths. For example passing-d public/jswill makejsbuildoutputapp.jsrather thanpublic/js/app.js.
For example to build a single package to support our application, we can run
this command to produce a single script containing JS.Packages, jQuery and
Application, since Application depends on jQuery:
$ jsbuild --manifest public/js/manifest.js \
--root public/js/ \
--external \
Application
The resulting script is printed to stdout. Note that jsbuild does not do
any minification of the files your provide, it simply locates the required
modules and concatenates them. You should deal with minifying the resulting
file separately.
If you just want to build a file containing parts of JS.Class you want to use,
run jsbuild with the names of the required modules:
jsbuild JS.Set JS.Deferrable
Organising bundles
As a project grows, it often becomes likely that you don’t want all your
modules and their dependencies in one file. Although this minimizes HTTP
round-trips, it means the entire bundle must be re-downloaded when any part of
it changes. For this reason many people keep stable libraries in one bundle
and their more volatile application code in another. jsbuild lets you create
such bundles using a simple JSON file.
The file lists a number of bundles, each of which has an include field and
an optional exclude field, both of which can be a list or a single item. The
include field specifies which objects from the manifest should go into that
bundle, while exclude specifies which dependencies should be skipped,
usually because they are provided by another bundle you will load separately.
Items given to exlude can be object names from the manifest, or other bundle
names to exclude everything provided by that bundle and any bundle it depends
on.
For example, let’s split our files into stable libraries and our application code:
// bundles.json
{
"libs": {
"include": [ "jQuery" ]
},
"app": {
"exclude": "libs",
"include": "Application"
}
}
We can then pass bundle names instead of object names to jsbuild to create
the bundled files. Remember to pass -b bundle.json to tell it where your
bundles are stored.
$ jsbuild -m public/js/manifest.js -b bundles.json -r public/js -o paths libs https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js $ jsbuild -m public/js/manifest.js -b bundles.json -r public/js -o paths app public/js/app.js
If we removed the line "exclude": "libs" from the app bundle, we would
instead get this output, where jQuery has been included before our own files:
$ jsbuild -m public/js/manifest.js -b bundles.json -r public/js -o paths app https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js public/js/app.js