Skip to content
A browser-side javascript library for overriding import maps
JavaScript CSS HTML
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src Automatically updating the UI when js api makes change to overrides. Aug 13, 2019
test Improving UI Jun 29, 2019
.babelrc Initial implementation of UI Jun 11, 2019
.gitignore Initial implementation Apr 14, 2019
LICENSE Initial commit Apr 12, 2019
README.md Adding jsdelivr badge to Readme Aug 13, 2019
package-lock.json Upgrading dependencies Jul 27, 2019
package.json
rollup.config.js Initial implementation of UI Jun 11, 2019
serve.json Improving UI Jun 29, 2019
yarn.lock Adding getUrlFromPort function and defaulting port numbers to localhost. Aug 13, 2019

README.md

import-map-overrides

A browser javascript library for being able to override import maps. This works with native browser import maps or with the SystemJS polyfill for import maps.

Motivation

import-map-overrides-ui

Import maps are a way of controlling which url to download javascript modules from. The import-map-overrides library allows you to dynamically change the url for javascript modules by storing overrides in local storage. This allows developers to override individual modules to point to their localhost during development of a module, without having to boot up a local environment with all the other modules and a backend server.

You should not use import-map-overrides as the only import map on your page, since you cannot count on everyone's local storage having valid values for all of your modules. Instead, import-map-overrides should be viewed as a developer experience enhancement and dev tool -- developers can develop and debug on deployed environments instead of having to boot up a local environment.

Installation

The import-map-overrides library is used via a global variable window.importMapOverrides. The global variable exists because import-map-overrides needs to be usable regardless of build config and without dependence on ESM modules, since once you use ESM modules you can no longer modify the import map.

It is preferred to install import-map-overrides with a <script> tag in your html file.

<!--
Make sure to put this BEFORE any <script type="module"> elements or any System.import() calls, but
AFTER all other import maps
-->
<script
  type="text/javascript"
  src="https://cdn.jsdelivr.net/npm/import-map-overrides/dist/import-map-overrides.js"
></script>
<!-- optionally include the UI for import map overrides -->
<import-map-overrides-full></import-map-overrides-full>

Alternatively, you can use it as an npm package:

npm install --save import-map-overrides
# Or
yarn add import-map-overrides
/*
Make sure this js file gets executed BEFORE any <script type="module"> elements or any System.import() calls,
but AFTER any other import maps that are on the page.
*/
import "import-map-overrides"; // this only will work if you compile the `import` down to an iife via webpack, rollup, parcel, etc

Configuration

If you are using import-map-overrides for native import maps, no configuration is required.

However, if you're using SystemJS as a polyfill for import maps, you'll need to tell import-map-overrides to make a <script type="systemjs-importmap"> element instead of <script type="importmap">. To do this, you must add a <meta> element to your html file before the import-map-overrides library is loaded.

<meta name="importmap-type" content="systemjs-importmap" />

Integration with other import maps

The import-map-overrides library can override a server-rendered inline import map, an import map that is loaded via src="", or any other import map. The key to making this work is to ensure that the import-map-overrides library is loaded after all other import maps that are on the page, but before the first <script type="module"> or System.import().

Javascript API

import-map-overrides provides the following functions. Note that these functions are always put onto window.importMapOverrides, even if you installed it as an npm package.

window.importMapOverrides.getOverrideMap()

Returns the override import map as an object. The returned object represents the overrides that will take effect the next time you reload the page, including any additions or removals you've recently made after the current page's acquiringImportMaps boolean was set to false.

const overrideMap = window.importMapOverrides.getOverrideMap();
console.log(overrideMap);
/*
{
  "imports": {
    "module1": "https://mycdn.com/module1.js",
    "lodash": "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.core.js"
  }
}
*/

window.importMapOverrides.addOverride(moduleName, url)

Accepts a string moduleName and a string url as arguments. This will set up an override which takes effect the next time you reload the page. Returns the new override import map.

Note that if you provide a port instead of a full url, that import-map-overrides will provide a default url to your localhost.

window.importMapOverrides.addOverride("react", "https://unpkg.com/react");

// Alternatively, provide a port number. Default url will be //localhost:8085/module1.js
window.importMapOverrides.addOverride("module1", "8085");

window.importMapOverrides.removeOverride(moduleName)

Accepts a string moduleName as an argument. This will remove an override which takes effect the next time you reload the page. Returns a boolean that indicates whether the override existed.

const wasRemoved = window.importMapOverrides.removeOverride("vue");
console.log(wasRemoved); // Either true or false

window.importMapOverrides.resetOverrides()

Removes all overrides from local storage, so that the next time the page is reloaded an override import map won't be created. Accepts no arguments and returns the reset override import map.

window.importMapOverrides.resetOverrides();

window.importMapOverrides.getUrlFromPort(moduleName, port)

This API is used internally by import-map-overrides to create a full url when calling addOverride() with just a port number:

const defaultOverrideUrl = window.importMapOverrides.getUrlFromPort(
  "module1",
  "8085"
);
console.log(defaultOverrideUrl); // "//localhost:8085/module1.js"

The getUrlFromPort function is exposed as an API to allow you to customize the logic yourself:

window.importMapOverrides.getUrlFromPort = (moduleName, port) =>
  `http://127.0.0.1:${port}/${moduleName}.js`;

// Now whenever you call `addOverride()` with a port number, your custom logic will be called
window.importMapOverrides.addOverride("module1", "8085");
console.log(window.importMapOverrides.getOverrideMap().imports.module1); // "http://127.0.0.1:8085/module1.js"

Events

The import-map-overrides library fires an event called import-map-overrides:change on the window whenever the override import map changes. The event is a CustomEvent that has no detail property.

Example usage:

window.addEventListener("import-map-overrides:change", logImportMap);

// Later on you can remove the event listener
window.removeEventListener("import-map-overrides:change", logImportMap);

function logImportMap(evt) {
  console.log(window.importMapOverrides.getOverrideMap());
}

User Interface

The UI for import-map-overrides gives visual indication when any module is overridden, so that you know whether to blame your override or not when things are broken. It also lets you view and modify urls for all the modules in your import map.

Usage

You use the import-map-overrides UI via web components. This means you just need to put some HTML into the DOM in order for it to work. You have three options for the UI, depending on how much you want to customize the UI:

<!--
  The full UI, including the "trigger" button that pops up the UI.

  If you omit the show-when-local-storage attribute, the yellow/orange rectangle always shows.
  When you have the show-when-local-storage attribute, the yellow/orange rectangle will only show
  when the user has set a local storage value of "true" for the key specified.

  For example, in the below example you must run the follow command in order to see the full-ui.
  localStorage.setItem('overrides-ui', true);
 -->
<import-map-overrides-full
  show-when-local-storage="overrides-ui"
></import-map-overrides-full>

<!-- Alternatively, just the black popup itself -->
<import-map-overrides-popup></import-map-overrides-popup>

<!-- Or if you only want the actual import map list and UI for overriding -->
<import-map-overrides-list></import-map-overrides-list>

Not using the UI

The UI is completely optional. If you don't want to use it, simply don't include the <import-map-overrides-full> custom element in your page. Additionally, you can use the /dist/import-map-overrides-api.js file instead of /dist/import-map-overrides.js, which avoids downloading the code for the UI and reduces the library size.

You can’t perform that action at this time.