Home
Home
All Posts

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:

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.

Want to receive approximately one email every month with new articles, tools, and references I've discovered? Sign up below.

Read past issues.

Home
Social Links
Site References