web-dev-qa-db-fra.com

Produire un module ES en utilisant webpack

Avec Rollup, je peux sortir un module ES simplement en réglant l'option format sur 'es'. Comment puis-je faire la même chose avec webpack? Si ce n'est pas possible maintenant, Webpack a-t-il l'intention de l'ajouter?

La seule chose que j'ai trouvée dans le documentation pour output.libraryTarget qui mentionne les modules ES est la suivante:

libraryTarget: "commonjs-module" - Exposez-le avec le module.exports objet (output.library est ignoré), __esModule est défini (il est fileté comme module ES2015 en mode interop)

Cependant, ce n'est pas clair pour moi. Est-ce la même chose que libraryTarget: "commonjs2" avec la seule différence que __esModule est défini? Qu'est-ce que le "mode interop"?

38

Webpack2 n'a pas encore de bibliothèque appropriéeTarget, il ne génère pas d'ensembles ES6. De l’autre côté Si vous regroupez votre bibliothèque dans CommonJS, les regroupeurs ne pourront pas exécuter Tree Shaking, sans pouvoir éliminer les modules inutilisés. Cela est dû au fait que les modules ES sont encore en développement et que personne n’expédie les bundles ES au navigateur, alors que Webpack est principalement utilisé pour créer des bundles activés par le navigateur.

De l'autre côté, si vous publiez une bibliothèque, vous pouvez fournir à la fois les cibles CommonJS (umd) et ES, grâce à clé "module" dans le paquet. Json . En fait, vous n'avez pas besoin de webpack pour publier ES target, il vous suffit d'exécuter babel sur chaque fichier pour le faire passer à la version standard es2015. Par exemple, si vous utilisez react, vous pouvez exécuter babel uniquement avec le paramètre "react". Si votre source est déjà ES 2015 sans fonctionnalités supplémentaires, vous pouvez diriger le module directement vers votre fichier src/index.js:

//package.json
...
  "module": "src/index.js"
  "main": "dist/your/library/bundle.js
...

J'ai trouvé pratique d'utiliser babel pour gérer export v from 'mod' instructions dans mon index.js principal, j'ai donc 1 fichier de module exportant tous mes modules. Cela est possible avec les extensions babel-plugin-transform-export-export (également incluses dans le préréglage stage-1).

Je repère cette approche de la bibliothèque react-bootstrap, vous pouvez voir les scripts dans leur github (ce sont des webpack1). J'ai un peu amélioré leurs scripts dans mon réactif sigma repo , n'hésitez pas à copier les fichiers suivants qui feront ce dont vous avez besoin:

config/babel.config.js
scripts/buildBabel.js
scripts/es/build.js
scripts/build.js // this is command line controller, if you need just ES you don't need it

Regardez également lib target (scripts/lib/build.js et .babelrc), je fournis des modules trans transpilés pour que les utilisateurs de bibliothèque ne puissent inclure que les modules dont ils ont besoin, même sans spécifier explicitement la nécessité de l'ES ("react-sigma/lib/Sigma /"). , particulièrement utile si votre bibliothèque est lourde et modulaire!

13
Max Vorobjev

Tout d’abord, je voudrais préciser la différence entre le commonJS et le commonJS2

CommonJS ne prend pas en charge l'utilisation de module.exports = function() {} utilisée par node.js et de nombreuses autres implémentations commonJS.

Webpack2 Utilise le concept de regroupement du code de bibliothèque et pour son utilisation généralisée et pour le rendre compatible avec le travail dans différents environnements, nous utilisons l'option -- libraryTarget

Maintenant, la partie ici répondra à vos deux questions

Les options de bibliothèque possibles supportées dans webpack2 Sont

  • libraryTarget: "umd", // enum
  • libraryTarget: "umd-module", // ES2015 module wrapped in UMD
  • libraryTarget: "commonjs-module", // ES2015 module wrapped in CommonJS
  • libraryTarget: "commonjs2", // exported with module.exports
  • libraryTarget: "commonjs", // exported as properties to exports
  • libraryTarget: "AMD", // defined with AMD defined method
  • libraryTarget: "this", // property set on this
  • libraryTarget: "var", // variable defined in root scope

Interlop a la signification suivante

Afin d'encourager l'utilisation de modules CommonJS et ES6 , lors de l'exportation un default export avec aucun autre exportsmodule.exports sera défini en plus de exports["default"] comme indiqué dans l'exemple suivant

export default test;
exports["default"] = test;
module.exports = exports["default"];

Donc, fondamentalement, cela signifie que le commonJS-module Peut être utilisé par exposant comme module.exports En utilisant le interloping avec module ES2015 enveloppé dans commonJS

Plus d'informations sur interloping peuvent être trouvées dans ceci blogpost et le stackoverflow link .

L'idée de base est dans ES6 les propriétés d'exportation et d'importation ne peuvent pas être modifiées mais dans commonJS, cela fonctionne très bien comme le nécessite des modifications au moment de l'exécution donc il a ES2015 est entrelacé avec le commonJS .

Mettre à jour

Webpack 2 donne la possibilité de créer la bibliothèque pouvant être regroupée et incluse.

Si vous souhaitez que votre module soit utilisé dans différents environnements vous pouvez le regrouper en tant que bibliothèque en ajoutant les options de bibliothèque et en le exportant dans votre environnement spécifique. Procédure mentionnée dans le docs .

Un autre exemple simple sur la façon d'utiliser commonjs-module

Le point important à noter ici est babel ajoute exports.__esModule = true À chaque es6 module Et lors de son importation, le _interopRequire Vérifie cette propriété.

__esModule = true Doit être défini uniquement sur exportation de la bibliothèque. Il doit être défini sur le exports du module entry. Modules internes n'avez pas besoin de __esModule, C'est juste un hack babel.

Comme mentionné dans la documentation

__esModule Est défini (il est lié comme ES2015 Module en interop mode)

Utilisation telle que mentionnée dans le cas de test

export * from "./a";
export default "default-value";
export var b = "b";

import d from "library";
import { a, b } from "library";
19
Pritish Vaidya