-
-
Notifications
You must be signed in to change notification settings - Fork 254
Configuring Packages for jspm
This guide covers how to configure packages for jspm compatibility, describing the package.json configuration options. If you are stuck, or would like to request help with getting a package configured for jspm, simply post an issue to the registry repo here.
When requesting a package, either downloaded with the CLI or through a CDN endpoint, jspm uses certain optional package.json configuration properties to be able to understand the package.
These package.json configurations extend the existing package.json spec, shared with npm.
For a given package, we need to work out where it is located. Currently the endpoints supported are GitHub and npm. It is important to ensure that the package source is well-maintained and ideally an official repository for the package. Otherwise the package will go out of date over time.
Packages hosted on npm are best to use because they are normally small and already configured correctly to work with their dependencies managed through jspm.
When using npm, most of the steps here can be skipped, and one can get straight to just testing the repo.
If loading a module from npm that is not CommonJS style you will need to add a
format
override to the package as all modules are by default treated as CommonJS on npm.
When using a package from GitHub one has to consider file size quite carefully.
- Try downloading the release tarball and see how long it takes. This will be replicated every time someone downloads this package, so ensure this isn't too big.
- For GitHub projects that use custom GitHub release assets, the asset zip file or tarball will be used instead of cloning the git repo, which allows a much quicker download when installing Bootstrap for example.
Having worked out the package name, it will be something like github:some/repo
or npm:repo
. Now we can start testing package configuration.
The jspm CLI provides an option to specify the package override for testing.
Simply add the -o
option to an install to set the package override:
jspm install github:twbs/bootstrap -o "{ registry: 'jspm', main: 'js/bootstrap', shim: { 'js/bootstrap': ['jquery'] } }"
The registry property is always needed for jspm to understand dependencies. npm packages use
registry: "npm"
by default.
Once tested the exact override can then be included in the registry with a pull request.
The options for these overrides are described in the rest of this document.
When creating a package.json file for a package, sometimes it can be necessary to separate the jspm-specific configuration from npm or other systems.
The jspm
package.json property allows us to do this:
{
"name": "my-package",
"jspm": {
"main": "jspm-main"
}
}
When processed, the jspm
property is treated as an override of the underlying package.json itself.
You may wish to use the jspm
property for all jspm configuration, or not use it at all - this is entirely your own preference.
The first thing to consider is what package files jspm is using for the package. Most packages have different folders for testing and development, so it is important to indicate exactly where our module files are to be used.
If the main module files for use are all in a folder within the package, we can set this folder with the directories.lib
option.
For example, if we had the main libraries in a folder called src
, we would write:
{
"directories": {
"lib": "src"
}
}
jspm will now only use this folder within the package. All file paths will now be relative to this lib folder.
Here's another example. Suppose you have the following override, notice the repetitive dist/famous-angular
:
{
"registry": "jspm",
"main": "dist/famous-angular",
"dependencies": {
"famous": "^0.3.0",
"angular": "^1.2.0",
"css": "*"
},
"shim": {
"dist/famous-angular": {
deps: ["./famous-angular.css!"]
}
}
}
You can change that to the following to avoid repeating the dist/
directory in main:
and shim:
:
{
"registry": "jspm",
"directories" : {
"lib": "dist"
},
"main": "famous-angular",
"dependencies": {
"famous": "^0.3.0",
"angular": "^1.2.0",
"css": "*"
},
"shim": {
"famous-angular": {
deps: ["./famous-angular.css!"]
}
}
}
Set directories.baseURL
to be the folder that will be served, relative to package.json. For example, if at the root of your project is package.json along with a public
folder, and jspm is being run at the root of the project, then set directories.baseURL
to public
so that jspm will install packages to public/jspm_packages
and write config.js to public/config.js
.
{
"jspm": {
"directories": {
"baseURL": "public"
}
}
}
Then you can, for example, npm install -g live-server; live-server public
to serve everything from the public
folder.
Set directories.packages
to the path where you want jspm to install packages, relative to jspm's working directory and package.json. The default is ./jspm_packages
. For example, continuing the above directories.baseURL
example:
// package.json
{
"jspm": {
"directories": {
"baseURL": "public"
"packages": "public/pkgs"
}
}
}
<!DOCTYPE html>
<html>
<head>
<title>Project with Infamous</title>
<meta charset="utf-8" />
</head>
<body>
<script src='/pkgs/system.src.js'></script><!-- relative to public/ -->
<script src='config.js'></script><!-- relative to public/ -->
<script type="module">
System.import('app'); // relative to public/
</script>
</body>
</html>
Just like npm, if there are only a few files (or folders) to include, they can be individually listed in a files array.
This array also supports glob patterns.
Also like npm, if there are certain specific files or folders to ignore, they can be listed in an array.
Both files
and ignore
are applied before using the directories.lib
so should still include the lib
path.
While jspm will detect the module format automatically and accurately in the majority of cases, it is typically best to include the module format.
Options are es6
, amd
, cjs
and global
.
When loading modules from
npm
, the module format is treated ascjs
by default and no automatic detection is run. To load modules of another format you will need to override this property manually.
This is the module name of the main entry point of the package. It isn't necessary to include the .js
extension, or start the name with relative syntax (./
), although this will still work.
jspm only understands dependencies in the context of a registry. Without a registry set, jspm will ignore the dependencies.
When loading packages from npm, jspm will set the default registry to npm
, and treat the dependencies accordingly.
When loading packages from other endpoints, the registry must be set explicitly to jspm
to enable the dependencies and allow for jspm registry support.
The jspm
registry allows dependencies of the following forms:
name: version
name: name@version
name: endpoint:name@version
Typically semver-compatible versions should be used of the form ^x.y.z
. The full description of allowed version formats are described in the version section on https://jspm.io.
Shims allow you to specify dependencies for specific files in a project. This configuration is identical to the way it is defined in other loaders such as RequireJS.
Packages written as globals need a shim configuration to work properly in a modular environment. To shim a file some/global.js
within the package, we can write:
{
"shim": {
"some/global": {
"deps": ["jquery"],
"exports": "globalExportName"
}
}
Both deps
and exports
are optional.
exports
is detected automatically by the SystemJS loader as any globals written by the script. In most cases this detection will work out correctly.
The shortcut form of "some/global": ["jquery"]
is also supported if there is no exports
.
Shims aren't limited to globals. As in the above directories.lib examples, a shim can be used to define the dependencies of any file in a project:
{
"registry": "jspm",
"directories" : {
"lib": "dist"
},
"main": "famous-angular",
"dependencies": {
"famous": "^0.3.0",
"angular": "^1.2.0",
"css": "*"
},
"shim": {
"famous-angular": {
deps: ["./famous-angular.css!"]
}
}
}
That shim configuration will cause dist/famous-angular.css
to get loaded first (by the systemjs css plugin) any time dist/famous-angular.js
gets loaded.
This configuration option is rarely used since dependencies
covers most rewriting needs. But sometimes internal requires within a module need to be rewritten in various other ways.
Map configuration will rewrite internal requires to point to different local or external modules.
Consider a package which includes its own dependency, dep
located at third_party/dep
. It could have a require statement internally something like:
require('dep');
In order to use the local version, we can write:
{
"map": {
"dep": "./third_party/dep"
}
}
Map configuration can also reference external packages without the ./
.