When using JavaScript modules we often import with node package paths. When loading JavaScript in the browser, the browser will not know where the package folder is because it is not a relative directory path. The path points to a node_modules directory where our packages are installed.

import { html } from 'lit-element';

When using tools like Webpack or Rollup, they update the paths and bundle this code for us. This is a problem if we want to prototype without any build tools.

Web Component APIs in the browser are relatively low-level APIs. We can use tools like lit-html and lit-element to provide high-level abstractions. When using lit-element to build Web Components, we typically need a build step. Lit-element ships as modern es2015+ JavaScript; however, it uses import paths that are not relative file paths. Luckily an upcoming browser feature called import maps are a potential solution to save us from build tooling.

JavaScript Module Import Maps

Import maps are a new proposed feature for JavaScript modules. Import maps allow us to tell the browser when it sees one path for a module to use another. Our example we import from lit-element.

import { html } from 'lit-element';

With an import map we can tell the browser to swap out lit-element to use a CDN URL instead.

<script type="importmap">
  {
    "imports": {
      "lit-html": "https://unpkg.com/lit-html@latest/lit-html.js?module"
    }
  }
</script>

This snippet maps our import to our new path which points to a CDN version of the lit-html package.

import { html } from 'https://unpkg.com/lit-html@latest/lit-html.js?module';

This mapping is helpful since we don’t want to have to use a build step to transform the paths for us. Import maps are still a newly proposed feature, so to use them, we need to use a shim JavaScript file to provide the functionality. We will use the es-module-shims polyfill.

<!doctype html>
<html>
  <head>
    <script defer src="https://unpkg.com/es-module-shims@latest/dist/es-module-shims.js"></script>
    <script type="importmap-shim">
      {
        "imports": {
          "lit-html": "https://unpkg.com/lit-html@latest/lit-html.js?module",
        }
      }
    </script>
    <script type="module-shim">
      ...
    </script>
  </head>
  <body>
   ...
  </body>
</html>

To use the shim, we have to suffix the module types with shim, so the polyfill/shim has time to process and update the paths. To use lit-element, we need to update a few paths since lit-element has a few different import paths.

<script type="importmap-shim">
  {
    "imports": {
      "lit-html": "https://unpkg.com/lit-html@latest/lit-html.js?module",
      "lit-element": "https://unpkg.com/lit-element@latest/lit-element.js?module",
      "lit-html/lit-html.js": "https://unpkg.com/lit-html@latest/lit-html.js?module",
      "lit-html/lib/shady-render.js": "https://unpkg.com/lit-html@latest/lib/shady-render.js?module"
    }
  }
</script>

Now that we have the import map set up out we can start using lit-element in our JavaScript.

<!doctype html>
<html>
  <head>
    <script defer src="https://unpkg.com/es-module-shims@latest/dist/es-module-shims.js"></script>
    <script type="importmap-shim">
      {
        "imports": {
          "lit-html": "https://unpkg.com/lit-html@latest/lit-html.js?module",
          "lit-element": "https://unpkg.com/lit-element@latest/lit-element.js?module",
          "lit-html/lit-html.js": "https://unpkg.com/lit-html@latest/lit-html.js?module",
          "lit-html/lib/shady-render.js": "https://unpkg.com/lit-html@latest/lib/shady-render.js?module"
        }
      }
    </script>
    <script type="module-shim">
      // you can also set a external script src with type "module-shim"
      import { LitElement, html, css } from 'lit-element';

      class XComponent extends LitElement {
        static get styles() {
          return css`
            :host {
              color: red;
            }
          `;
        }

        render() {
          return html`
            Hello from lit-element!
          `;
        }
      }

      customElements.define('x-component', XComponent);
    </script>
  </head>
  <body>
    <x-component></x-component>
  </body>
</html>

Lit HTML Web Component with Import Maps

We can now import from lit-element and start writing our Web Components. Import maps with lit-element is excellent for quick prototyping and trying out different Web Component libraries. Want to learn more about lit html check out my other blog post Web Components Building Web Components with lit-html.

View Demo Code