'Webpack: How to export directly to global (without .default) containing stylesheet imports?

Context

I have a webpack.config.js like this:

/* Something here */

module.exports = {
  entry: {
    main: './src/index.js'
  },
  output: {
    library: 'MyClass',
    libraryTarget: 'umd',
    path: path.resolve(__dirname, 'lib'),
    filename: `package.js`
  },
  ...
}

My ./src/index.js looks like this:

import MyClass from 'src/myClass'
import 'src/myStyle.css'

export default MyClass

Problem

While this works fine, it exposes MyClass class to window object as:

console.log(window.MyClass)
=> Module {default: ƒ, __esModule: true, Symbol(Symbol.toStringTag): "Module"}

This way, I cannot invoke my class by using:

new MyClass();
=> TypeError: MyClass is not a constructor

I have to invoke it like:

new MyClass.default();
=> MyClass { ... }

I can solve the problem by doing something like this in my ./src/index.js:

const MyClass = require('src/myClass')
module.exports = MyClass

/* in browser */
new MyClass()
=> Good, works fine

However, this way, I cannot import my stylesheet:

const MyClass = require('src/myClass')
import 'src/myStyle.css'

module.exports = MyClass
=> TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

Edit

The following way also solves the problem, but is done without an export:

/* webpack.config.js */
module.exports = {
  entry: {
    main: './src/index.js'
  },
  output: {
    /* Need to remove library related props */
    // library: 'MyClass',
    // libraryTarget: 'window',
    path: path.resolve(__dirname, 'lib'),
    filename: `package.js`
  },
  ...
}

/* ./src/index.js */
import MyClass from 'src/myClass'
import 'src/myStyle.css'

window.MyClass = MyClass

Question

Is there a way in Webpack for me to export a module directly to global without having to invoke with .default and at the same time import a stylesheet in the entry file?



Solution 1:[1]

Use output.libraryExport in your webpack.config.js. (ref)

Along with output.libraryTarget set to umd, output.libraryExport tells Webpack which property to be exported as the global variable named by the output.library.

In your case, in addition to your original configuration, set output.libraryExport to default is equivalence to append the following snippet after your compiled code.

window.MyClass /*output.library*/ = module.exports.default /*output.libraryExport*/

The configuration will be as follows.

/* Something here */

module.exports = {
  entry: {
    main: './src/index.js'
  },
  output: {
    library: 'MyClass',
    libraryTarget: 'umd',
    libraryExport: 'default',  // export the default as window.MyClass
    path: path.resolve(__dirname, 'lib'),
    filename: `package.js`
  }
}

Have a try in the console.

> window.MyClass
class {...}

Solution 2:[2]

If your script is only designed to run in the web browser only why not just update window explicitly:

import MyClass from 'src/myClass'
import 'src/myStyle.css'

window.MyClass = MyClass;

I think this is a lot clearer than using indirection.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 momocow
Solution 2 Andrew Skirrow