javascript - Webpack : Comment exporter directement vers le global (sans .default) en contenant des imports de feuilles de style ?


Contexte

J'ai un webpack.config.js comme ceci :

/* Something here */

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

Mon ./src/index.js ressemble à ceci :

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

export default MyClass

Problème

Bien que cela fonctionne correctement, cela expose la classe MyClass à l'objet window comme suit :

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

De cette façon, je ne peux pas invoquer ma classe en utilisant :

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

Je dois l’invoquer comme ceci :

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

Je peux résoudre le problème en faisant quelque chose comme ceci dans mon ./src/index.js :

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

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

Cependant, de cette façon, je ne peux pas importer ma feuille de style :

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

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

Modifier

La façon suivante résout également le problème, mais elle est faite sans un 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

Y a-t-il un moyen dans Webpack pour que je puisse exporter un module directement dans le global sans avoir à invoquer avec .default et en même temps importer une feuille de style dans le fichier d'entrée ?

Réponse #1

Utilisez output.libraryExport dans votre webpack.config.js. (réf)

En plus de définir output.libraryTarget sur umd, output.libraryExport indique à Webpack quelle propriété doit être exportée en tant que variable globale nommée par le output.library.

Dans votre cas, en plus de votre configuration originale, définir output.libraryExport sur default équivaut à ajouter l'extrait suivant après votre code compilé.

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

La configuration sera la suivante.

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

Essayez dans la console.

> window.MyClass
class {...}

Réponse #2

Si votre script est conçu uniquement pour s'exécuter dans le navigateur web, pourquoi ne pas simplement mettre à jour window de manière explicite :

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

window.MyClass = MyClass;

Je pense que c'est beaucoup plus clair que d'utiliser l'indirection.