Import Maps, Now Available in All Browsers, Improves Module Resolution in JavaScript

MMS Founder
MMS Bruno Couriol

Article originally posted on InfoQ. Visit InfoQ

With Safari 16.4 recently adding support for import maps, JavaScript developers can now use import maps in all modern browsers. Older browsers can use a polyfill. Import maps bring better module resolution for JavaScript applications.

An import map allows resolving module specifiers in ad-hoc ways. With import maps, developers can separate the referencing of module dependencies from their location (on disk or a remote server). Developers can use bare module specifiers to import dependencies (e.g., lodash in import { pluck } from "lodash";). Dedicated tooling can handle the mapping between dependencies and their location without touching the application code.

As an immediate result of cross-browser support, the JSPM CLI has been relaunched a few days ago as an import map package management tool. The JSPM CLI for instance automatically outputs the following import map for the lit library:

<script type="importmap">
{
  "imports": {
    "lit": "https://ga.jspm.io/npm:lit@2.7.0/index.js"
  },
  "scopes": {
    "https://ga.jspm.io/": {
      "@lit/reactive-element": "https://ga.jspm.io/npm:@lit/reactive-element@1.6.1/reactive-element.js",
      "lit-element/lit-element.js": "https://ga.jspm.io/npm:lit-element@3.3.0/lit-element.js",
      "lit-html": "https://ga.jspm.io/npm:lit-html@2.7.0/lit-html.js",
      "lit-html/is-server.js": "https://ga.jspm.io/npm:lit-html@2.7.0/is-server.js"
    }
  }
}
</script>

Guy Bedford, core open source contributor to the JSPM CLI and maintainer of the import maps polyfill, explained how import maps can improve tooling and developer experience when using JavaScript modules:

JSPM respects package.json version ranges and supports all the features of Node.js module resolution in a browser-compatible way. It supports arbitrary module URLs and CDN providers e.g. by just adding --provider unpkg to the install command (or even local node_modules mappings via --provider nodemodules).
Better apps are written when there are fewer steps between the developer and their tools, fewer steps between development and production, and fewer steps between applications and end-users.

Alternatively, developers can provide the import maps manually and remove the need for build tools in some cases. The Lit team provided such a use case on Twitter (see online playground). One Twitter user commented:

Frontend without needing to install npm is something I’ve dreamed of for years.

The import map WhatWG specification details a mechanism to resolve module specifiers based on the content of two fields (imports and scopes) passed as a JSON object. The following import map

{
  "imports": {
    "a": "/a-1.mjs",
    "b": "/b-1.mjs",
    "c": "/c-1.mjs"
  },
  "scopes": {
    "/scope2/": {
      "a": "/a-2.mjs"
    },
    "/scope2/scope3/": {
      "b": "/b-3.mjs"
    }
  }
}

results in the following module resolutions (using relative URLs for brevity):

Imgur

The previous table illustrates that when a script (the referrer) located in /scope2/scope3 imports code from module a (the specifier), that module will be loaded from the /a-2.mjs location. As there is no map configured under the scope /scope2/scope3 for module a, the resolution algorithm uses the closest available (i.e., the one for /scope2).

Import maps are included in HTML files with a tag in the section of the document:


<script type="importmap">
... JSON import map here
</script>

Older browsers will benefit from the es-module-shims polyfill. Support of import maps in browsers can be detected as follows:

if (HTMLScriptElement.supports('importmap')) {  

Developers can refer to the full import maps specification for additional technical details.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.