Configuring Packages for jspm

Guy Bedford edited this page Mar 8, 2016 · 72 revisions
Clone this wiki locally

Package.json Specification

This guide covers how to configure new and existing packages for installation through jspm. If you are stuck getting a package to install properly, feel free to post an issue for assistance here.

jspm uses certain optional package.json configuration properties to be able to understand the package, which it reads during the installation. These properties are documented below.

These package.json configurations extend the existing package.json spec, shared with npm.

Finding the Package Source

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.

npm

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.

GitHub

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.

Testing 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 "{ main: 'js/bootstrap', shim: { 'js/bootstrap': ['jquery'] } }"

Once tested the exact override can then be included in the registry with a pull request.

Overrides are stored in the package.json of the project under the "overrides" property so that future installs will use the same override for subsequent jspm install operations.

The options for these overrides are described in the rest of this document.

Prefixing Configuration

You can write all package properties at the base of the package.json, or if you don't want to change existing properties that you'd like to use specifically for npm, you can write your jspm-specific configuration inside the jspm property of package.json, and jspm will use these options over the root level configuration options.

For example:

{
  "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.

Package Files

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.

directories.lib

Note that if you are creating an override for a third-party package, it is best not to set directories.lib as this is a breaking change to the package interface.

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 as the whole package. All file paths will now be relative to this lib folder, including for use in the other package configuration options such as main, shim and map.

files

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.

ignore

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.

Package Module Format

While jspm will detect the module format automatically and accurately in the majority of cases, it is typically best to include the module format.

format

Options are esm, amd, cjs and global.

When loading modules from npm, the module format is treated as cjs by default and no automatic detection is run. To load modules of another format you will need to override this property manually.

Module format esm (ECMAScript Module) currently isn't used in package.json.

Main Entry Point

main

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.

Package Dependencies

registry

jspm understands dependencies in the context of a registry.

When loading packages from npm, jspm will set the default registry to npm, and treat the dependencies accordingly.

When loading packages from GitHub, the dependencies property is ignored without a registry property being present, as jspm has no way of knowing what the dependencies mean for existing GitHub repos.

Setting the registry property also determines how jspm interprets the package. For example, a GitHub package with registry: "npm" will, along with getting its dependencies from npm, be interpreted as CommonJS and support features like directory and JSON requires, exactly as if it had been installed from the npm endpoint to begin with.

A package on GitHub with its registry property set to registry: "jspm" will have its dependencies treated as jspm-style dependencies.

dependencies

The dependencies in the package.json take the following form:

  "dep": "registry:package@version"
  "dep": "package@version"

The second shorter form will use the value of the registry set by the registry property in the package.json.

The name of the dependency in the package can be any custom alias, that is then only locally scoped to that specific package.

Typically semver-compatible versions should be used of the form ^x.y.z. Tilde ranges, ~x.y.z are also supported. Ranges without a patch or minor are also supported - x, x.y, ~x.y, ^x.y.

Shim Configuration

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.

shim

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 are no exports.

Map Configuration

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

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"
  }
}

It can also be useful to reference a package by its own name within submodules:

{
  "map": {
    "thispackage": "."
  }
}

We can then have internal requires to import 'thispackage/module' resolve correctly.

Map configuration can also reference dependency submodules.

We can also exclude modules entirely by mapping them to the empty module:

{
  "map": {
    "jquery": "@empty"
  }
}

The value returned will then be a Module object with no exports.