Before getting Jam, make sure you install Node.js.
Jam can then be installed using NPM (Node Package Manager), which comes installed with Node.js.
npm install -g jamjs
Jam installs packages to ./jam by default (this can be easily configured in you project's package.json). This directory contains your installed packages and a specially configured require.js you can use to load them in the browser.
$ jam install jquery
This will download the latest version of jQuery from the package repository and install it. You can list installed packages using jam ls.
$ jam ls
* jquery 1.7.2
Jam will also fetch any dependencies for the target package.
$ jam install backbone
installing from repositories backbone
Building version tree...
repositories checking "backbone"
repositories checking "underscore"
downloading http://packages.jamjs.org/backbone/backbone-0.9.2.tar.gz
downloading http://packages.jamjs.org/underscore/underscore-1.3.3.tar.gz
extracting /home/caolan/.jam/cache/backbone/0.9.2/backbone-0.9.2.tar.gz
extracting /home/caolan/.jam/cache/underscore/1.3.3/underscore-1.3.3.tar.gz
installing underscore@1.3.3
installing backbone@0.9.2
updating jam/jam.json
updating jam/require.config.js
updating jam/require.js
OK
When using jam ls, packages that are in your
jam.dependencies property in package.json (direct dependencies) are
prefixed with an asterisk, other packages (indirect dependencies) are not.
Packages that are not directly depended on may be marked as unused if
your project's dependencies change.
$ jam ls
underscore 1.3.3
* jquery 1.7.2
* backbone 0.9.2
To use the packages you've installed, include the specially configured
require.js script in the page.
All your other dependencies can then be loaded using the
require function.
<script src="jam/require.js"></script>
<script>
require(['jquery'], function ($) {
$(document.body).text('Hello, world!');
});
</script>
You can load any number of modules in this way, without polluting the global namespace. Jam can also bundle the immediately useful modules into a single file for production use, and you can load less frequently used code in the background when it's needed. All of this can be done without changing the above code.
The first argument to require is an array of module names
to load, these are then passed to the callback containing the code you
want to run. For more information, see the RequireJS docs.
<script src="http://requirejs.org/docs/release/2.0.1/minified/require.js"></script>
<script src="jam/require.config.js"></script>
If you want to use a non-configured version of RequireJS (perhaps from
a CDN, or existing app) you can use jam/require.config.js to set up the
correct paths for the installed jam packages. However, you probably
want to avoid the extra request and just include the
jam/require.js file instead.
If you've used Node.js and NPM, you may be familiar with keeping
a list of dependencies in a project-level package.json file.
You can also put a list of Jam dependencies in this file, which allows
you to lock to specific versions of dependencies.
{
"name": "myproject",
"version": "0.0.1",
"description": "An example Node.js project",
"dependencies": {
// NPM dependencies go here...
"async": "0.1.22"
},
"jam": {
"dependencies": {
// Jam dependencies go here...
"jquery": "1.7.1",
"underscore": null
}
}
}
Of course, it doesn't have to be a Node.js project for you to add a
package.json file with your Jam packages!
If you'd prefer to install JavaScript dependencies to a location
other than ./jam, you can set the jam.packageDir
property in package.json. You can also use jam.baseUrl
to tell Jam which directory to make relative package paths from. For example:
{
"jam": {
"packageDir": "public/vendor",
"baseUrl": "public",
"dependencies": {
...
}
}
}
This will install packages to public/vendor and set up the
package paths so you can include public/vendor/require.js
from a file at public/*. Remember, these are file paths
relative to package.json, not URLs.
When a new version of a library is released it can be a pain to keep your projects up to date. With Jam, when packages are updated you can upgrade to all the latest versions with just one step.
$ jam upgrade
Running this command will check the package repositories for any updates and install any upgraded packages. You can also specify individual packages to upgrade:
$ jam upgrade jquery
Of course, automatically upgrading to the latest version isn't always
a good idea. If an installed package depends on a specific version of
a library, then the correct version will always be retained.
Dependencies with specific version requirements in your project's
package.json will also not be upgraded.
To upgrade these, you should modify the acceptable versions in
package.json first. If you don't care which version is
installed, you can set the version to just null.
Packages tied to a specific version also show up when doing
jam ls
$ jam ls
underscore 1.3.3
* jquery 1.6.2 [locked 1.6.2]
* backbone 0.9.2
To remove a package:
$ jam remove jquery
If you remove a package that has dependencies installed,
and those dependencies are not used by any other packages,
you can remove them using jam clean.
This will prompt you to remove any packages not included in your
package.json (and not a dependency of one of those packages).
If you decide you need to keep a package from this list, you should
add the package to your package.json to make sure it is not
removed by mistake.
$ jam clean
Building version tree...
The following directories are not required by packages in
package.json and will be REMOVED:
jam/underscore
Continue [Y/n]:
For best performance in production, you should always compile modules into a single file. It's much quicker than waiting for require.js to parse then have it make the requests asynchronously. For complex applications, which use modules only in specific circumstances or on a few pages, you may want to compile a base set of modules that are needed immediately, then load the additional modules in the background only when they are needed.
Jam offers an easy to use command which combines and minifies your installed packages, and can even include code from your own project.
$ jam compile output.js
This will combine all the packages you have installed into a single
file, including the configured require.js library.
You can include this file in place of require.js and get
all the benefits of the optimized download without having to change
any JavaScript code in your application.
In fact, you may find it useful to replace jam/require.js
with the output of the compile command, so you don't even have to change
the script tag which includes it. By doing this you get the benefits
without having to change anything in your application.
$ jam compile jam/require.js
Of course, the next time you jam install or otherwise
modify the package list, the jam/require.js file will be
rewritten and will not include the compiled modules from before.
You would have to re-run the compilation command.
Because of this, it makes sense to add this step to your build system.
Add it to a Makefile or script you normally use to create production
versions of your code, preferably creating a new copy of the whole
project (eg myapp/dist) and running the
jam compile step in the new directory.
You may not want to include all the installed packages in the compiled output, or you may want to include some modules from your project that are not being managed by Jam. Thankfully, you can specify individual modules to include in the compiled output.
$ jam compile -i myapp/base -i jquery -o output.js
You can use package names or paths to AMD modules from your own
application. The output will include the specified modules and their
dependencies. Any modules not included will still be accessible using
require.js, they'll just be loaded asynchronously as you
need them.
If you know you won't be loading additional resources in the background
you can add --almond to the compile command to have it use
the almond.js shim to
provide the require and define functions. This saves a little off the
download size, which may be significant on mobile devices.
If you're specifying individual modules to include in jam's compiled
output, you can make it easier to manage by using a single, top-level
module for your application. This module should include all the other
modules and top-level dependencies you need. Then, when doing
jam compile you need only specify this file and Jam will
find all the dependencies from there.
define('myapp/app', [
'jquery',
'myapp/foo'
],
function ($, foo) {
return {
init: function () {
// add you app initialization code here
// ...
}
};
});
<script src="jam/require.js"></script>
<script>
require(['myapp/app'], function (app) {
app.init();
});
</script>
Then, to include all the immediately required files into a single download, simply do:
$ jam compile -i myapp/app -o output.js
By doing it this way, you can add that command to your build script and not
have to update it when your app's dependencies or module structure changes.
Instead, you just manage compiled dependencies in myapp/app.js.
In the majority of cases, you'll want to just include your modules in a single compiled download. Occasionally, however, you may have large resources which are only needed in very specific circumstances. In this situation, it can be useful to load the resources in the background only once they are needed.
The following examples build on the files from the previous section: "Make it easy to find dependencies".
<button id="testbtn">Test</button>
<script src="jam/require.js"></script>
<script>
require(['myapp/app'], function (app) {
app.init();
});
</script>
define('myapp/app', [
'jquery',
'myapp/foo'
],
function ($, foo) {
return {
init: function () {
$('#testbtn').click(function () {
// by making a require call here, we can load this
// asynchronously, only once we've clicked the button!
require(['myapp/bar'], function (bar) {
alert(bar.message);
});
});
}
};
});
define('myapp/bar', [], function () {
return {message: 'Hello, world!'};
});
Now, if you were to compile according to the previous section, including
only myapp/app:
$ jam compile -i myapp/app -o jam/require.js
Then open index.html in the browser, you should notice
that on page load only require.js is fetched (since it
has myapp/foo and jquery compiled). But, when you click the "Test"
button the myapp/bar module is fetched in the background.
The package.json file inside each package directory provides
Jam with important meta-data, including description, version information and
required dependencies. It is loosely based on the Package Descriptor File
format described in the
Packages 1.0 specification
available as part of CommonJS. Often, you'll find that these
files are compatible with the package.json used
for publishing to NPM.
{
"name": "example",
"version": "0.0.1",
"description": "An example Jam package",
"jam": {
"dependencies": {
"jquery": ">1.4.2",
"underscore": ">1.3.1"
},
}
}
These are the essential properties every package.json
must have, though you might omit the dependencies field if the
package has no dependencies. Ideally, you should provide as much
information about the package as possible.
{
"name": "example",
"version": "0.0.1",
"description": "An example Jam package",
"homepage": "http://example.com",
"keywords": [
"package",
"example"
],
"jam": {
"dependencies": {
"jquery": ">1.4.2",
"underscore": ">1.3.1"
},
"main": "example.js",
"shim": {
"deps": ["jquery"],
"exports": "Example"
},
"include": [
"example.js",
"README"
]
},
"maintainers": [
{
"name": "Bill Smith",
"email": "bills@example.com",
"web": "http://www.example.com"
}
],
"contributors": [
{
"name": "Mary Brown",
"email": "maryb@example.com",
"web": "http://www.example.com"
}
],
"bugs": {
"mail": "dev@example.com",
"web": "http://www.example.com/bugs"
},
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/mit-license.php",
}
],
"repositories": [
{
"type": "git",
"url": "http://github.com/example/example.git"
}
],
"github": "http://github.com/example/example"
}
| name | The name of the package. Ideally, this should be all lowercase, and if necessary, use a "-" as a separator between words (eg, "example-package"). |
|---|---|
| version | A version string conforming to the Semantic Versioning requirements (http://semver.org). See the section on versioning for more information. |
| description | A brief description of the package. |
| homepage | URL string for the package website. | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| keywords | An Array of string keywords to assist users searching for the package. | ||||||||
| jam |
|
||||||||
| maintainers | Array of maintainers of the package. Each maintainer is a hash which must have a "name" property and may optionally provide "email" and "web" properties. | ||||||||
| contributors | Array of hashes each containing the details of a contributor. Format is the same as for maintainers. | ||||||||
| bugs | URL for submitting bugs. Can be mailto or http. | ||||||||
| licenses | Array of licenses under which the package is provided. Each license is a hash with a "type" property specifying the type of license and a url property linking to the actual text. If the license is one of the official open source licenses the official license name or its abbreviation may be added with the "type" property. If an abbreviation is provided (in parentheses), the abbreviation must be used. | ||||||||
| repositories | Array of repositories where the package can be located. Each repository is a hash with properties for the "type" and "url" location of the repository to clone/checkout the package. A "path" property may also be specified to locate the package in the repository if it does not reside at the root. | ||||||||
| github | The appropriate GitHub page for the package. This mean the package details page on the jam website will display a link to GitHub and a watchers count in search results. This can sometimes be inferred from the repositories property. |
During development, you may want to use your package in a project
while continuing to work on it. Using jam link you can
create a symlink to the package directory and add it to your paths
in jam/require.js.
$ jam link /path/to/dev-package
Remember that your symlink locations are unlikely to be useful to anyone else that checks your code out. This should only be used during development until it makes sense to install a copy in your project.
To stop Jam from trying to upgrade linked packages you
should add "linked" as the version in your project's
package.json for the package you are linking.
Jam uses semantic versioning (http://semver.org).
Loosely speaking, this translates to MAJOR.MINOR.PATCH,
for example 1.2.3.
If you are directly publishing a library from it's source repository,
without modifications, then you can simply publish it with the version
number of the library itself (provided it conforms to the semantic
versioning requirements). If you make any modifications to the upstream
library to prepare it for publishing to the Jam repositories, you
should add a Jam version number. For example 1.2.3-jam.1,
1.2.3-jam.2.
This allows you to update the Jam-specific code without changing the
upstream version number.
To publish a package so others can install it, you must
first sign-up for an account on this site.
Once you have an account, just do jam publish inside your
package directory to pack and upload it. Then repeat the publish
command every time you want to release a new version.
If you make a mistake and want to publish over an existing version,
use the -f or --force flag. Be warned, this
is not recommended, since it will not prompt people using the previously
published copy to update.
If you would like to remove a package from the Jam repositories, use
jam unpublish PACKAGE, where PACKAGE is
the name of the package you'd like to remove. You can specify a single
version to remove by doing jam unpublish PACKAGE@VERSION,
eg jam unpublish example@1.2.3.
To make your package easy to find, you can use a number of pre-defined
categories in your package.json file. You can see the list
of available packages on the packages page.
The categories must be typed exactly as shown, and are case-sensitive.
{
"categories": ["Frameworks", "DOM"],
...
}
http://groups.google.com/group/jamjs