AMD, CommonJS and ES6 module loader
Next-generation module loading in all browsers today.
For the loader documentation and getting started guide, read below.
For a basic introduction and explanation with examples, see https://jspm.io.
The loader can be included from the CDN or locally. The CDN version can be useful for quick experimentation and is also suitable for production use.
Include the following script in the page:
loader.js with a script tag:
es6-module-loader.js will then be included automatically and the Traceur parser is dynamically included from
traceur.js when loading an ES6 module only.
Typically one would include a configuration file immediately after the loader script, although this can be done inline as well.
baseURL sets the folder where local scripts will be loaded. By default it is set to the HTML page URL.
.js extension, and with baseURL rules.
For example, modules can be loaded from the baseURL with the syntax
~/my/module -> [baseURL]/my/module.js
index.html page we can then load a module from the baseURL folder with:
Since we set the baseURL to
/lib, we can write:
Note that when running locally, ensure you are running from a local server or a browser with local XHR requests enabled. If not you will get an error message.
For Chrome on Mac, you can run it with:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --allow-file-access-from-files &> /dev/null &
In Firefox this requires navigating to
security.fileuri.strict_origin_policyin the filter box and toggling the option to false.
It is recommended to write modular code in either AMD or CommonJS. Both are equally supported by jspm, with the format detected automatically.
For example, we can write modular CommonJS:
var subModule = require'./submodule/submodule';//...subModulesomeMethod;//...
and load this with
jspm.import('~/app') in the page.
Note: always use relative requires of the form
../to reference modules in the same package. This is important within any package for modularity.
jspm provides an AMD compatibility layer, with the goal of supporting as much of the RequireJS test suite as possible to ensure functioning of existing AMD code.
To create the
require globals as AMD globals, simply include the following
<script> tag immediately after the inclusion of the jspm loader:
This should replicate a fair amount of RequireJS functionality, and support is improving over time.
Note that AMD-style plugins are not supported.
jspm is an ES6 module loader. It will detect and load ES6 modules, parsing them with Traceur dynamically. This allows for dynamic loading of ES6 without a build step, although a build step still needs to be run to transpile ES6 back to ES5 and AMD for production. This use case will grow over time.
Read more about ES6 modules and module loaders at the ES6 Module Loader polyfill repo.
Global scripts can also be loaded with jspm, and any globals they write to the
window object will be converted into a special separate module object for the global.
This provides careful protection against global collisions, allowing global scripts to write to the same global variables without conflict.
Most global scripts will still need some shim configuration as in RequireJS to set their dependencies.
Endpoints provide collections of packages that can be downloaded or served over CDN.
Currently the following endpoints are supported:
Use of these endpoints is entirely optional, and custom endpoints can easily be created or overrided in the loader.
GitHub and npm both have endpoint services provided by jspm, allowing easy access to their modules.
The following will work without any installation necessary:
// load the latest stable version of underscore from npmjspmimport'npm:lodash-node/modern/objects/isEqual';// load the latest stable version of Bootstrap, from the 'js' folder in the Bootstrap release on GitHubjspmimport'github:twbs/bootstrap/js/bootstrap';// load the latest minor version of jquery from GitHubjspmimport'github:firstname.lastname@example.org/jquery';
In the above examples, the following module names are converted directly into the following URLs:
npm:lodash-node/modern/objects/isEqual -> https://npm.jspm.io/lodash-node/modern/objects/isEqual.js github:twbs/bootstrap/js/bootstrap -> https://github.jspm.io/twbs/bootstrap/js/bootstrap.js github:email@example.com/jquery -> https://firstname.lastname@example.org/jquery.js
The endpoint servers then provide the correct modular code from the package and version specified.
The CDN runs over SPDY so that all requests can travel over a single connection, and SPDY push is used to send module dependencies so that a new round trip is not needed everytime a dependency of a module is discovered.
To create a custom endpoint, use the configuration:
jspmconfigendpoints:myendpoint: '';// now jspm.import('myendpoint:hello') ->
Endpoints are independent CDNs. Other examples of services that would be appropriate for endpoints include Bitbucket, Google Code, etc. The NodeJS server running the npm and GitHub CDNs will be open sourced when ready to allow anyone to host a custom service endpoint, as well as a mirror of the GitHub or npm endpoints. For more information about endpoints, read the wiki here.
Instead of writing
github:email@example.com, typically one would write
jquery in all local application code.
We then map
jquery -> github:firstname.lastname@example.org with global map config for our application.
jspmconfigbaseURL: '/lib'map:jquery: 'github:email@example.com';
This means that any import/require for
jquery in any module will now get the exact jQuery version we want.
This is far better than specifying the full endpoint directly as it makes it very easy to update jQuery to a new version or endpoint. This is the most important configuration option for dependency-managed packages.
It can be difficult to know exactly what the most maintained endpoint is for a specific package and remember this endpoint each time.
Instead of needing to know
github:twbs/bootstrap is the maintained package endpoint for Bootstrap, the jspm registry provides a simple service to remember the main endpoint for libraries.
We simply write:
And if no other map configuration applies, the loader will convert this into the URL:
bootstrap -> https://registry.jspm.io/bootstrap.js
This module simply forwards to the correct location at
Use of the jspm registry is also entirely optional. The
registryURL can also be changed to be a local folder or another URL with the configuration:
The registry is still growing, and a list of the modules currently in the registry can be found here. Additions can be made with pull requests, or requested as issues.
The jspm registry, GitHub and npm endpoints use simple version conventions to provide version-managed packages.
When no version is specified, the latest stable version is used.
@ sign can be used to indicate a version.
Latest Stable Version
Latest Revision of Minor Version
This supports both version names and semvers:
Generally it is advised to write import/requires without any version or endpoint specified, and then use the package map configuration to set the endpoint and minor version.
This provides the most flexibility.
For example, in config.js:
jspmconfigbaseURL: '/lib'map:'jquery': 'firstname.lastname@example.org''bootstrap': 'github:email@example.com''underscore': 'npm:firstname.lastname@example.org';
While the CDN endpoints make it very convenient to create and load modules without the friction of installation, it is easy to switch to installing packages locally at any time.
With the jspm CLI, any endpoint package or registry package can be directly installed:
jspm install jquery bootstrap underscore
The CLI will then update the
config.js configuration file, as well as the
package.json and all packages will then be loaded locally from the same server.
To get started with the CLI, follow the guide at the jspm CLI page.
All other configuration in jspm is package-specific to ensure complete configuration modularity.
Package configuration is injected automatically from the package.json file by both the CDN and the jspm CLI when installing packages locally.
This configuration allows for easy usage of external packages without having to manually set up complex configuration.
The package-specific configuration options set the main entry point, module format, map and shim.
For example, here is the package configuration that is injected when downloading Bootstrap:
jspmconfigpackages:'github:email@example.com':main: 'js/bootstrap'format: 'global'shim:'js/bootstrap': 'jquery';
Map configuration can also be set at the package level, allowing for dependency version support and avoiding name conflicts in dependencies.
This sets the main entry point for the package. When the package is requested directly by name, eg:
this will then load
js/bootstrap.js, as if we had written:
jspm automatically detects the module format of files using regular expression detection techniques, but this comes with processing cost and perhaps the detected format may not be the format intended.
format property for a package will disable any detection and ensure that the module files are treated accordingly.
The options for format are:
Map configuration set within a package will only apply to dependencies of that package.
This is useful when two packages may refer to the same module name, but expect different underlying versions or implementations.
Shim configuration allows dependencies for global scripts to be enforced, just like RequireJS.
In the example,
will load Bootstrap only after loading jQuery.
More advanced shim configuration can also be set, allowing the exporter to be defined as well:
jspmconfigpackages:'github:firstname.lastname@example.org':shim:'lib/jquery':exports: 'jQuery''github:email@example.com':shim:imports: './jquery'exports: 'jQuery.somePlugin';
When developing locally, you may want to automatically cache bust the local URLs.
For this, set the
urlArgs configuration option:
jspmconfigurlArgs: '?bust=' + getTime;jspmimport'./test'; // requests [baseURL]/test.js?bust=1383745775497
jspm.import('#google Port Lligat Slab, Droid Sans !font')
The name of the plugin is by default the file extension before the
!, or the name can be provided after with
!pluginName when the plugin name is not the same as the resource extension name.
By default, plugins are loaded from the jspm registry, as the exact plugin name.
To submit a plugin, create a pull request on the registry page.
These are different from RequireJS in that they are extension-based plugin names:
some/module.coffee is a CoffeeScript file.
The plugin name can also be specified if not identical to the extension:
The plugin itself is loaded from the resource name
[pluginname]. This name itself can be mapped with standard configuration:
Otherwise, plugins are loaded from the registry.
var CoffeeScript = require'./coffee-script';fetchurlcallbackCoffeeScriptcompilesource;errback;
Note the plugin here is written as CommonJS for an example only - any module format will work.