Ausgabe eines ES-Moduls mit Webpack

Lesezeit: 9 Minuten

Benutzer-Avatar
Michał Perłakowski

Mit Rollup kann ich ein ES-Modul ausgeben, indem ich einfach das setze format Option zu 'es'. Wie kann ich dasselbe mit Webpack machen? Wenn es jetzt nicht möglich ist, hat Webpack irgendwelche Pläne, es hinzuzufügen?

Das einzige, was ich in der gefunden habe Dokumentation für output.libraryTarget das ES-Module erwähnt, ist dies:

libraryTarget: "commonjs-module" – Setzen Sie es mit dem aus module.exports Objekt (output.library wird ignoriert), __esModule ist definiert (es ist als ES2015-Modul im Interop-Modus eingefädelt)

Allerdings ist mir das eher unklar. Ist es dasselbe wie libraryTarget: "commonjs2" mit dem einzigen Unterschied, dass __esModule ist definiert? Was ist der „Interop-Modus“?

  • FYI, das entsprechende Ticket im Webpack: github.com/webpack/webpack/issues/2933

    – jakub.g

    4. Februar 2019 um 10:18 Uhr

  • In ~3 Monaten, es wird 2022, das Ticket ist noch offen, auch das seit 2016! Muss wohl umziehen aufrollen!

    – Niket Pathak

    12. September 2021 um 13:31 Uhr


Benutzer-Avatar
Pritish Vaidya

Zunächst möchte ich den Unterschied zwischen den commonJS und commonJS2

CommonJS unterstützt nicht die Verwendung von module.exports = function() {} die verwendet wird von node.js und viele weitere commonJS Implementierungen.

Webpack2 verwendet das Konzept der Bündelung des Bibliothekscodes und für die weit verbreitete Verwendung und um ihn mit der Arbeit in verschiedenen Umgebungen kompatibel zu machen, verwenden wir die —BibliothekZiel Möglichkeit

Jetzt wird der Teil hier Ihre beiden Fragen beantworten

Die möglichen Bibliotheksoptionen, die in unterstützt werden webpack2 sind

  • 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 hat folgende Bedeutung

Um die Nutzung zu fördern CommonJS und ES6-Modulebeim Exportieren von a default export mit keinem anderen exports module.exports wird zusätzlich gesetzt exports["default"] wie im folgenden Beispiel gezeigt

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

Also im Grunde bedeutet es, dass die commonJS-module kann von verwendet werden aussetzen es als module.exports durch die Verwendung der interloping mit ES2015-Modul verpackt in commonJS

Mehr Infos über die interloping sind darin zu finden Blogeintrag und der Stackoverflow-Link dazu.

Die Grundidee ist drin ES6 Runtime-Export- und -Importeigenschaften können nicht geändert werden aber in commonJS das funktioniert gut als die erfordern Änderungen zur Laufzeit deshalb hat es ES2015 ist interlopiert mit dem commonJS.

Aktualisieren

Webpaket 2 bietet die Möglichkeit, die Bibliothek zu erstellen, die gebündelt und eingeschlossen werden kann.

Wenn Sie möchten, dass Ihr Modul in verschiedenen Umgebungen verwendet wird Anschließend können Sie es als Bibliothek bündeln, indem Sie die Bibliotheksoptionen hinzufügen und es an Ihre spezifische Umgebung ausgeben. Verfahren in der erwähnt Dokumente.

Ein weiteres einfaches Beispiel zur Verwendung des commonjs-Moduls

Wichtiger Hinweis hier ist babel fügt hinzu exports.__esModule = true zu jedem es6 module und beim Importieren fordert es die _interopRequire um diese Eigenschaft zu überprüfen.

__esModule = true müssen nur eingeschaltet werden Bibliothek exportieren. Es muss auf eingestellt werden exports des Eingangsmodul. Innere Module brauche nicht __esModulees ist nur ein Babel-Hack.

Wie in den Dokumenten erwähnt

__esModule ist definiert (es ist eingefädelt als ES2015 Modul ein Interop Modus)

Verwendung wie in der erwähnt Testfälle

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

import d from "library";
import { a, b } from "library";

  • Könnten Sie meine Hauptfrage beantworten: Ist es möglich, ein ES-Modul mit Webpack auszugeben? Auch, wie funktioniert commonjs-module Arbeiten Sie mit benannten Exporten?

    – Michał Perłakowski

    30. Dezember 2016 um 16:06 Uhr

  • Wenn Sie nicht verstehen, was ich in dem Update geschrieben habe, lautet die Antwort ja – indem Sie die Bibliotheksoption hinzufügen und den Testfall wie oben erwähnt exportieren.

    – Pritish Vaidya

    30. Dezember 2016 um 21:27 Uhr

  • commonjs-module und commonjs2 sind anscheinend gleichwertig an dieser Stellewobei ersteres möglicherweise veraltet ist.

    – Stiggler

    27. März 2017 um 21:53 Uhr

Benutzer-Avatar
Max Worobjev

Webpack2 hat noch kein relevantes libraryTarget, es gibt keine ES6-Bundles aus. Von der anderen Seite Wenn Sie Ihre Bibliothek in CommonJS bündeln, können Bundler Tree Shaking nicht ausführen und nicht verwendete Module entfernen. Das liegt daran, dass sich ES-Module noch in der Entwicklung befinden, sodass niemand ES-Bundles an Browser versendet, während Webpack hauptsächlich zum Erstellen browserfähiger Bundles verwendet wurde.

Auf der anderen Seite können Sie, wenn Sie eine Bibliothek veröffentlichen, sowohl CommonJS- (umd) als auch ES-Ziele bereitstellen, dank “Modul”-Schlüssel im Paket. json. Eigentlich brauchen Sie kein Webpack, um das ES-Ziel zu veröffentlichen. Alles, was Sie tun müssen, ist, babel für jede Datei auszuführen, um sie auf den es2015-Standard zu bringen. Wenn Sie beispielsweise reagieren verwenden, können Sie babel nur mit der Voreinstellung “react” ausführen. Wenn Ihre Quelle bereits ES 2015 ohne zusätzliche Funktionen ist, können Sie das Modul direkt auf Ihre src/index.js verweisen:

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

Ich fand es bequem, mit babel umzugehen export v from 'mod' Anweisungen in meiner Hauptindex.js, also habe ich 1 Moduldatei, die alle meine Module exportiert. Das wird mit babel-plugin-transform-export-extensions erreicht (ebenfalls im Stage-1-Preset enthalten).

Ich sehe diesen Ansatz in der React-Bootstrap-Bibliothek, Sie können Skripte in ihrem Github sehen (sie sind webpack1). Ich habe ihre Skripte in meinem etwas verbessert Repo-Sigma Repozögern Sie nicht, die folgenden Dateien zu kopieren, die das tun, was Sie brauchen:

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

Sehen Sie sich auch das lib-Ziel (scripts/lib/build.js und .babelrc) an. Ich stelle transpilierte lib-Module bereit, damit Bibliotheksbenutzer nur Module einschließen können, die sie benötigen, auch ohne dass ES explizit require(“react-sigma/lib/Sigma/”) angibt. , besonders nützlich, wenn Ihre Bibliothek schwer und modular ist!

  • Das Problem, das ich beim Importieren gefunden habe src/index.js direkt ist, dass es nicht funktioniert, wenn die ursprüngliche Quelle Bilder, Sass usw. importiert, da Ihre Loader in webpack.config normalerweise ausschließen node_modules für diese Dateitypen.

    – Reihe1

    30. August 2017 um 4:14 Uhr


  • node_modules vom babel-loader ausgeschlossen, da Bibliotheken bereits transpiliert geliefert werden, brauchen wir dort kein babel. Wenn die Quelle Bilder oder andere Assets importieren muss, sollte die Konfiguration mit einem geeigneten Loader erweitert werden, z. B. File-Loader oder Sass-Loader mit Einstellungen zum Einschließen von node_modules, falls erforderlich. Bilder referenzieren oder CSS bewährte Verfahren ist es, alle statischen Inhalte in den statischen Ordner Ihrer Anwendung zu kopieren.

    – Max Worobjev

    30. August 2017 um 13:46 Uhr

  • Der Nachteil dabei ist, dass beim Erstellen einer Komponentenbibliothek oder eines ähnlichen Modultyps, der andere Assets importiert, jede Anwendung, die Ihr Modul verwendet, mit allen geeigneten Loadern konfiguriert werden muss. Es fügt der Webpack-Konfiguration der App viel Cruft hinzu und ist außerdem spröde, da die Bibliothek möglicherweise nur mit bestimmten Versionen von Plugins/Loadern kompatibel ist. Es wäre schön, Webpack ohne Bündelung/Konvertierung in CJS zu verwenden und gleichzeitig beim Erstellen der Bibliothek Nicht-JS-Module in importierbare Äquivalente umzuwandeln

    – M Müller

    5. Januar 2019 um 17:49 Uhr

Benutzer-Avatar
Nate Levin

Was ist die beste Nicht-Hacky-Lösung?

Offenbar, diese Funktion kommt in Webpack 5

Update: Webpack 5 wurde veröffentlicht, aber unterstützt dieses Verhalten immer noch nicht.

Update 2: Siehe dieser Kommentar was es so aussehen lässt, als würde es bald kommen.

Aktualisierung 3: Die neueste Version von Webpack sollte diesen Anwendungsfall unterstützen 🎉! (Obwohl es scheint, dass die Implementierung noch etwas fehlerhaft ist.

Wenn Sie ältere Versionen von Webpack verwenden müssen, können Sie die in beschriebenen Schritte verwenden Dies Blog-Beitrag, um ein Plugin zu verwenden, das die Ausgabe eines ES-Moduls ermöglichen kann.

Wenn Sie den obigen Blogpost verwenden (der Beispielcode des Posts ist ein wenig daneben), führen wir zuerst aus

npm i -D @purtuga/esm-webpack-plugin

Wir können dann einstellen webpack.config.js Zu dem Folgendem:

const EsmWebpackPlugin = require("@purtuga/esm-webpack-plugin");
module.exports = {
    mode: "development",
    entry: "index.js",
    output: {
        filename: "consoleUtils.js",
        library: "LIB",
        libraryTarget: "var"
    },
    //...
    plugins: [
        new EsmWebpackPlugin()
    ]
}

Dann können wir die Datei einfach wie gewohnt verwenden.

import func from "./bundle.js";

func();

Siehe auch dieses Problem die diese Funktion verfolgt.

  • Da diese Funktion derzeit nicht von Webpack unterstützt wird, werden alle Lösungen immer hacky sein. Der einzige Unterschied zu Ihrem Vorschlag besteht darin, dass der Hacky-Ansatz vom Plugin übernommen wird, anstatt direkt von Ihnen übernommen zu werden.

    – colxi

    11. Dezember 2020 um 16:10 Uhr

  • @colxi Natürlich ist die eigentliche Lösung des Plugins hacky, aber Wir müssen uns nicht mit irgendetwas Hacky befassen. Dies ist besonders für Anfänger einfach, da es sich um eine sehr kleine Modifikation handelt.

    – Nate Levin

    11. Dezember 2020 um 18:53 Uhr


Benutzer-Avatar
colxi

Wenn es Ihnen nichts ausmacht, Ihrem Paket eine zusätzliche Datei hinzuzufügen, können Sie diese Problemumgehung als Lösung verwenden, die Ihnen dies ermöglicht verteilen/importieren Sie Webpack-Bundles als ES6-Module:

Aufbau

webpack.config.js

output: {
    path: path.resolve('./dist'),
    filename: 'bundle.js',
    library: '__MODULE_DEFAULT_EXPORT__',
    libraryTarget: 'window',
    libraryExport: 'default'
  },

./dist/index.js (wir müssen diese Datei erstellen)

import './bundle.js'
const __MODULE_DEFAULT_EXPORT__ = window.__MODULE_DEFAULT_EXPORT__
delete window.__MODULE_DEFAULT_EXPORT__
export default __MODULE_DEFAULT_EXPORT__

package.json (wichtig, wenn Sie Ihr Modul verteilen werden)

  "main": "dist/index.js",

Wie es funktioniert :

  • Webpack gibt das Bundle an aus /dist/bundle.jsVerwendung der window wie libraryTarget Methode. Laut meiner Konfiguration macht dies das Paket Standardexport verfügbar als window.__MODULE_DEFAULT_EXPORT__sobald es importiert ist.
  • Wir erstellen einen benutzerdefinierten “Loader”: ./dist/index.jsdie die importiert /dist/bundle.js wählt die window.__MODULE_DEFAULT_EXPORT__ löscht es aus der window Objekt (Bereinigung), weist es einer lokalen Variablen zu und exportiert es als ES6-Export.
  • Wir konfigurieren unsere package.json um auf unseren “Loader” hinzuweisen: ./dist/index.js
  • Wir können jetzt regelmäßig auftreten import MyDefaultExportName from './dist/index.js'

Hinweis: Diese Lösung, wie sie hier dargestellt wird, ist alles andere als perfekt und hat einige Nachteile und Einschränkungen. Obwohl es Raum für Verbesserungen gibt 🙂

1060760cookie-checkAusgabe eines ES-Moduls mit Webpack

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy