How to expose an es6 module globally

11,960

Solution 1

You should combine export default class Foo with the library and libraryTarget settings in Webpack's config. Something like:

// src/Foo.js
export default class Foo { ... }

// webpack.config.json
{
  "output": {
    "library": "Foo",
    "libraryTarget": "var"
  }
}

You should be able to use the library as window.Foo once the bundle has been loaded.

Solution 2

This is basically the same issue as Exporting a class with Webpack and Babel not working , except that you have a named export instead of a default export. Your entry file should be

import {MyMod} from './mymod';
module.exports = MyMod;

or

module.exports = require('./mymod').MyMod;

If you don't want to do any of these and keep './src/mymod.js' as entry file, use a CommonJS export instead of an ES6 export in that file:

// mymod.js
exports.MyMod = class MyMod {
    constructor(aaa) {
        this.aaa = aaa;
    }
    toString() {
        return this.aaa;
    }
}
Share:
11,960

Related videos on Youtube

bldoron
Author by

bldoron

Updated on September 15, 2022

Comments

  • bldoron
    bldoron over 1 year

    I need to write a module that will be available on the window global.
    I'm using es6 to create the module and every single class I define has it's own file.
    I'm using webpack to babelify and bundle these classes.
    The entry point of my module is also the file containing the global to be exposed.

    I've tried every method to make this possibe, icluding:

    • expose-loader
    • import-loader
    • expoert-loader
    • output: library
    • black-magic :(

    Example of code I've tried:

    I want to get: window.MyMod

    // mymod.js
    export class MyMod {
        constructor(aaa) {
            this.aaa = aaa;
        }
        toString() {
            return this.aaa;
        }
    }
    

    // webpack.config
    var entries = [
        './src/mymod.js'
    ];
    module.exports = {
        ...,
        module: {
          loaders: [
                {
                    test: require.resolve('./src/mymod.js'),
                    loader: 'expose?MyMod'
                },
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                    query: {
                        presets: ['es2015']
                    }
                }
        ]
    }
    

    This only gets me an object MyMod on the window that contains MyMod as a constructor.

    Any help will be appreciated.

  • Felix Kling
    Felix Kling over 7 years
    You might want to be more specific, otherwise it's not possible to help you.
  • bldoron
    bldoron over 7 years
    Sorry, you're correct. Your first solution is impossible, because i'm not importing the file anywhere, I need it to be built. The second one, I did try, but this: require.resolve('./src/mymod.js') and this require.resolve('./src/mymod.js').MyMod resulted in the same window.MyMod.MyMod.
  • bldoron
    bldoron over 7 years
    Tried that, it didn't work. Resulted in an empty window.Foo object
  • Felix Kling
    Felix Kling over 7 years
    "Your first solution is impossible, because i'm not importing the file anywhere," I said you have to create a new entry file with that content, instead of using ./src/mymod.js as entry file. I.e. create a file ./src/entry.js with the content from my answer and configure webpack to use that: var entries = [ './src/entry.js'];
  • bldoron
    bldoron over 7 years
    I've been trying to avoid that, it sounds like a hack. I think I'll do what jquery did and somehow wrap the class in an anonymous self invoking function returning MyMod. I'll report back with this try- though it also is a hack.
  • Felix Kling
    Felix Kling over 7 years
    Well, you are trying to make ES6 modules work together with a tool that is built for CommonJS modules. If you don't want use any of the suggestions and keep ./src/mymod.js as entry file then you should use a CommonJS module definition instead of ES6: exports.MyMod = class MyMod {};. Implementing a wrapper like jQuery does is completely unnecessary because that's exactly what webpack does for you.
  • ssube
    ssube over 7 years
    @bldoron did you set the entry in your config as well? I think that may be necessary to get a reliable global var.
  • bldoron
    bldoron over 7 years
    What finally worked was: module.exports = class MyMod {...} and exposing it as I did: test: require.resolve('./src/mymod.js'), loader: 'expose?MyMod'
  • Jacob Phillips
    Jacob Phillips over 5 years
    @bidoron can you write an answer that sums up how to do this? All I get is an empty global var.