JavaScript and Rollup: Replace ES6 imports with globals

JavaScript and Rollup: Replace ES6 imports with globals

The use case

You're using one or more third party libraries (React, Preact, Lodash, ...) in an ES6 library you're creating for the browser.

Don't bundle

Don't bundle the third party libraries with your library.

  • Your visitors might already have the third party libraries in their cache. If you bundle them with your library, then they're forced to download all of those bytes again.
  • If you change your library, then your visitors are forced to download everything again: your library and all of the bundled (and unchanged) third party libraries.

The solution

First, import and use the third party libraries in your code as you normally would.

import { h } from "preact";  // 3rd party
import htm from "htm";  // 3rd party

const html = htm.bind(h);

// ...

Second, add the third party libraries' script tags to your HTML. Be sure to use UMD bundles that export a global.

<script src="https://cdn.jsdelivr.net/npm/preact?umd"></script>
<script src="https://cdn.jsdelivr.net/npm/htm?umd"></script>

Third, find the exact name of the global that each third party library exports. For these two libraries, I loaded their script tags into a test HTML file, opened up the console, and found preact and htm. In this case the globals matched the library names, but that's not always the case.

Finally, configure Rollup to replace the ES6 dependencies with the globals.

import externalGlobals from "rollup-plugin-external-globals";
import { terser } from "rollup-plugin-terser";

export default {
  external: ["preact", "htm"],
  input: "src/library.js",
  output: [
    {
      file: "dist/library.js",
      format: "iife",
    },
    {
      file: "dist/library.min.js",
      format: "iife",
      plugins: [terser()],
    },
  ],
  plugins: [
    externalGlobals({
      preact: "preact",  // <- must match the global name
      htm: "htm",  // <- must match the global name
      ["a-dashed-3rd-party-library"]: "globalVariable"  // <- advanced example
    }),
  ],
};

You'll need rollup-plugin-external-globals to perform the replacement and rollup-plugin-terser to minimize your library's code.

That's it! Rollup will now convert

import { h } from "preact";  // 3rd party
import htm from "htm";  // 3rd party

const html = htm.bind(h);

// ...

to simply

const html = htm.bind(preact.h);

// ...

Summary

  • Don't bundle third party libraries with your browser library.
  • Use the third party libraries in your code as you normally would, and then
  • Use Rollup to replace the ES6 imports with globals.

Photo by Charles "Duck" Unitas on Unsplash