JSPM

JSPM 4.0 Release

JSPM 4.0 is now out, featuring a refreshed and opinionated standards-based workflow based on convention over configuration. It provides a modern workflow for working with native ESM in the browser using import maps:

Read the updated Getting Started guide for more info, or continue reading below for the background on how this release came together.

Standards Based Workflows

Leaning into standards means that developers can focus on writing JavaScript without learning custom build toolchains or frameworks. The JSPM 4.0 workflow takes advantage of the latest browser capabilities:

  1. Native ES Modules: Use standard import/export syntax without transpilation
  2. Import Maps: Handle dependency mapping directly in the browser
  3. TypeScript Type Stripping: TypeScript type stripping as the only code transform
  4. No Custom Loaders: Everything runs on standard browser semantics

This standards-first approach has several major benefits:

Import Map Package Management

One of the major changes in JSPM 4.0 is import maps are now treated as package management artifacts more like lock files than manifests for hand-editing.

All package management operations output by default to the new importmap.js import map injection script file. This is effectively a workaround for the lack of external import map support for an importmap.json file in browsers. This injection script approach only recently gained wide browser support thanks to the new multiple import maps feature.

We use the following new approach:

<script src="importmap.js"></script>
<script type="module">import 'app'</script>

Where the importmap.js injection script itself then directly inlines the new import map into the browser:

importmap.js

(map => {
  document.head.appendChild(Object.assign(document.createElement("script"), {
    type: "importmap",
    innerHTML: JSON.stringify(map)
  }));
})
({
  "imports": {
    "my-app": "./src/index.js"
    // ... imports
  },
  "scopes": {
    // ... scopes
  }
});

With the above, using just native browser semantics it is possible to run any JS application with an import map.

Package.json is the Manifest

Instead of hand-editing the importmap.js file, JSPM now fully determines what dependencies are needed at what versions and updates the map with full authority.

The user manifest for the application, and what entry points and dependency constraints to use is then taken from the local package.json file.

The key idea here is that we can define the application entry points from the package.json using the "name" and "exports" package.json fields.

For example, for a package.json containing:

{
  "name": "my-app",
  "exports": {
    ".": "./src/index.js"
  },
  "dependencies": {
    "foo": "1.2.3"
  }
}

JSPM will then know when the user runs jspm install that there should be a "my-app" import in the import map pointing to "./src/index.js".

It will then link (trace) that entry point and its dependencies in turn, populating dependencies into scopes while respecting the package.json "dependencies" resolution ranges.

As a result, the only imports at the top-level "imports" of the import map will be the enumerated "exports" entry points (which also support subpath patterns).

It was surprisingly hard to figure out these import map ergonomics for the project but this is a major simplification that forms the new convention for the project going forward.

We still support many map configuration options as before like --out, --map and --resolution flags (amongst others) for custom map inputs and outputs as well as for creating JSON and HTML files. In addition, jspm link is still supported (although may even be phased out eventually) for the more complex map manipulation workflows. But the important point here is that if we stop treating import maps as a user manifest and let JSPM own it as an artifact of its linking process that figures out mappings based on constraints, we get some really great ergonomics out of import maps development.

Hot Reloading Server

The JSPM 4.0 server (jspm serve) provides a development environment with instant hot module reloading built off the same conventions as install:

The hot reloading system works by injecting a Server Side Events connection into the import map injection script itself. When files change, the server notifies the client and ES Module Shims handles the reloading of only the affected modules, preserving application state supporting the import.meta.hot API.

The hot reloading server is made possible by ES Module Shims, which is used in JSPM to polyfill import map features in older browsers like multiple import maps support, recently adding support for hot reloading.

Building for Production

The semantics of jspm build follow from the same standards-based runtime semantics.

What makes this possible is that by clearly defining the application entry points, enforced from the start with jspm install, the package optimization is also fully well defined without having to set any extra build entry points or configurations.

This is very much the same thing as what the JSPM.IO CDN already does today for npm packages, but now available locally.

Future Directions

The ability to seamlessly run an online sandbox without a build step or proprietary infrastructure remains a primary goal of the project, and we are seeing this use case continue to grow as more sandboxes choose to build on top of JSPM, especially with the rapid growth of AI sandboxes.

Equally important are local-first workflows with minimal tooling.

These two approaches - online sandboxes and local-first workflows - have always been the two main aspects of JSPM. The first version of JSPM prioritized local workflows before demonstrating remote code loading capabilities, while in recent years the JSPM.IO CDN-first models have taken the front seat here.

Getting back to enabling completely CDN-free local workflows remains a major goal for the project and on the roadmap.

While provenance is crucial, equally important is avoiding vendor lock-in through standards. This standards-first philosophy is what we consider most critical to get right, and it's what this 4.0 release primarily represents.

JSPM 4.0 lays the groundwork for addressing these security concerns, and the project security focus will remain on these three problems: provider interchangeability via standards, CDN verification with integrity, and local provenance.

Next Steps

JSPM 4.0 represents a significant step toward bringing back standards-first local import map workflows and we continue to believe that unifying package management with import maps creates a natural workflow for web development both for online sandboxes and local development use cases.

Please try out the new release and let us know your feedback!