samullen
samullen

Reputation: 2530

Accessing webpack bundled libraries in the browser

I'm having trouble accessing a webpack bundled library from the browser.

Example: I have a class Foo

// foo.js

"use strict";

export default class Foo {
  constructor() {
    var bar = "bar";
  }
}

Foo is imported in src.js

// src.js

"use strict";
import Foo from "./foo.js";

The webpack config looks like this. The entry is src.js and the output file is bundle.js.

// webpack.config.js

module.exports = {
  entry: './src.js',
  output: {
    path: '.',
    filename: 'bundle.js',
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015']
        }
      },
    ]
  },
};

Webpack compiles everything okay, and I'm able to load it into my HTML file.

<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <script src="bundle.js"></script>
  <script type="text/javascript">
    var x = new Foo();
    console.log(x);
  </script>
</head>
<body>
</body>
</html>

it's at this point that I'm getting the error. For some reason, the bundled JS doesn't put the Foo class into a namespace the browser is able to access.

This is the error I get in Firefox:

ReferenceError: Foo is not defined[Learn More]

There's some configuration in WebPack I'm not grokking, I'm sure of it, but I've so far not been able to figure it out.

Upvotes: 27

Views: 12658

Answers (3)

Claies
Claies

Reputation: 22323

To make this code re-usable, you need to tell webpack you are authoring a Library.

From the webpack documentation:

To make your library available for reuse, add library property in webpack configuration.

To create your library, make the following change:

module.exports = {
  entry: './src.js',
  output: {
    path: '.',
    filename: 'bundle.js',
    library: 'fooLibrary', //add this line to enable re-use
  },
...

In order to use the library, you can then reference it in your other scripts:

<script type="text/javascript">
  var x = new fooLibrary.Foo();
  console.log(x);
</script>

Upvotes: 42

Sean Larkin
Sean Larkin

Reputation: 6420

Looks like 'var' is the default for output.libraryTarget therefore you should be able to define your output.library property and you will be able to access the var globally. https://webpack.js.org/configuration/output/#output-librarytarget

Upvotes: 2

GregL
GregL

Reputation: 38121

One of the major advantages of Webpack and ES2015 modules is that it stops polluting the global namespace by default.

Because of this, if you want to publish something on the global object, you have to do it explicitly. I recommend namespacing your classes to something unique to the application or company, so you don't risk a naming collision with anything else.

Upvotes: 1

Related Questions