Home

Export ES6 Class Globally with webpack

webpack creates its own scope for your bundle, but you can make it globally available.

In a previous article on distributing JavaScript libraries I used an example that uses webpack to build (and Babel to transpile/) an ES6 class and expose it as a global variable.

Most of this process came from an article on this very subject.

That articles states that there are only a few steps. I'll demonstrate those steps quickly with my HelloWorld example:

The Process

Let's say my main file is src/index.js, which looks like this:

src/index.js

import { HelloWorld } from "./components/hello-world";
module.exports = HelloWorld;

And my component looks like this:

src/components/hello-world.js

export class HelloWorld {
static log() {
console.log("Hello world!");
}

static write() {
document.body.append("Hello World!");
}
}

To make this class globally available I have to adjust my webpack config slightly:

webpack.config.js

const path = require("path");

module.exports = {
entry: "./src/index.js",
output: {
filename: "hello-world.js",
path: path.resolve(__dirname, "dist"),
libraryTarget: "var",
library: "HelloWorld",
},
};

I add two extra lines:

  • libraryTarget: 'var' tells webpack to make the library available as a global variable.
  • library: 'HelloWorld' names that global variable (in this case, it's HelloWorld).

The Problem

That's where the article got me, but there's a problem with it today. It causes this error:

Cannot assign to read only property 'exports' of object '#<Object>'

Essentially what that means is you can't mix ES6 imports with CommonJS exports.

The Fix

The thing is we need the CommonJS export for this to work. So, what do we do? Change the import to require so both use CommonJS. The most important piece, though, is that we append .default to the require so that we attach the ES6 module directly to the variable (as opposed to nested within its default object).

So, index.js changes to:

src/index.js

const HelloWorld = require("./components/hello-world").default;
module.exports = HelloWorld;

And the component's class name isn't necessary, so we can do this:

src/components/hello-world.js

export default class {
// ...
}

Now you can build and see the bundle available globally as HelloWorld, effectively exposing the two static methods in my example (log() and write()) direct on the HelloWorld object.

In other words, if you were to load the resulting bundle on a website, you'd have access to run both static methods like so:

HelloWorld.log(); // Logs "Hello World!" to the console.
HelloWorld.write(); // Appends "Hello World!" to the DOM's body.

Let's Connect

Keep Reading

Use Netlify to Host JavaScript Libraries

Netlify is built to host websites, but it can be a handy resource for JavaScript libraries, too.

Nov 30, 2018

WTF is webpack?

webpack has been helping us write modular front-end JavaScript for many years. Learn the basics of module bundling and why webpack is so powerful.

May 25, 2021

Simple JavaScript Pipeline with webpack

webpack has a reputation for being super complex and difficult to implement. But as its most basic, it can do a lot with little development effort. Let's walk through a simple example together.

May 28, 2021