javascript - Webpack: Como exportar diretamente para global (sem .default) contendo importações de folhas de estilo?


Contexto

Tenho um webpack.config.js assim:

/* Something here */

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

O meu ./src/index.js é assim:

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

export default MyClass

Problema

Embora isto funcione bem, expõe a classe MyClass ao objeto window da seguinte forma:

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

Desta forma, não posso invocar a minha classe usando:

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

Tenho de invocá-lo assim:

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

Posso resolver o problema fazendo algo assim no meu ./src/index.js:

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

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

No entanto, desta forma, não consigo importar a minha folha de estilos:

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

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

Editar

A seguinte forma também resolve o problema, mas é feita sem um 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

Pergunta

Há alguma forma no Webpack de eu exportar um módulo directamente para o global sem ter de invocar com .default e ao mesmo tempo importar uma folha de estilos no ficheiro de entrada?

Resposta #1

Use output.libraryExport no seu webpack.config.js. (ref)

Juntamente com output.libraryTarget definido como umd, output.libraryExport indica ao Webpack qual propriedade deve ser exportada como a variável global nomeada pelo output.library.

No seu caso, além da sua configuração original, definir output.libraryExport para default é equivalente a anexar o seguinte trecho após o seu código compilado.

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

A configuração será a seguinte.

/* 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`
  }
}

Tente na consola.

> window.MyClass
class {...}

Resposta #2

Se o seu script estiver concebido apenas para ser executado no navegador web, por que não atualizar explicitamente window:

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

window.MyClass = MyClass;

Acho que isto é muito mais claro do que usar indireção.