Ich habe ein relativ kleines NPM-Paket erstellt, das aus ungefähr 5 verschiedenen ES6-Klassen besteht, die jeweils in einer Datei enthalten sind. Alle sehen ungefähr so aus:
export default class MyClass {
// ...
}
Ich habe dann einen Einstiegspunkt für mein Paket eingerichtet, der folgendermaßen aussieht:
export { default as MyClass } from './my-class.js';
export { default as MyOtherClass } from './my-other-class.js';
Ich habe dann den Einstiegspunkt durch Webpack und Babel geführt und am Ende eine transpilierte und minimierte index.js erhalten
Das Installieren und Importieren des Pakets funktioniert einwandfrei, aber wenn ich Folgendes aus meinem Client-Code heraus mache:
import { MyClass } from 'my-package';
Es wird nicht nur "MyClass" importiert, sondern die gesamte Datei einschließlich aller Abhängigkeiten jeder Klasse (einige meiner Klassen haben große Abhängigkeiten).
Ich dachte mir, dass Webpack so funktioniert, wenn Sie versuchen, Teile eines bereits gebündelten Pakets zu importieren. Also habe ich meine lokale Webpack-Konfiguration so eingerichtet, dass node_modules/my-package
sie auch babel durchläuft, und dann versucht:
import { MyClass } from 'my-package/src/index.js';
Aber auch dies importiert jede einzelne Klasse, die von index.js exportiert wird. Das einzige, was so zu funktionieren scheint, wie ich es will, ist, wenn ich es tue:
import MyClass from 'my-package/src/my-class.js';
Aber ich würde viel lieber:
- Sie können die transpilierte und minimierte Datei importieren, damit ich webpack nicht anweisen muss, babel in node_modules und auszuführen
- Sie können jede einzelne Klasse direkt von meinem Einstiegspunkt importieren, anstatt den Pfad zu jeder Datei eingeben zu müssen
Was ist hier die beste Vorgehensweise? Wie erreichen andere ähnliche Setups? Ich habe festgestellt, dass GlideJS eine ESM-Version seines Pakets hat, mit der Sie nur die Dinge importieren können, die Sie benötigen, ohne beispielsweise babel durchlaufen zu müssen.
Das fragliche Paket: https://github.com/powerbuoy/sleek-ui
webpack.config.js
const path = require('path');
module.exports = {
entry: {
'sleek-ui': './src/js/sleek-ui.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
library: 'sleek-ui', // NOTE: Before adding this and libraryTarget I got errors saying "MyClass() is not a constructor" for some reason...
libraryTarget: 'umd'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
]
}
]
}
};
package.json
"name": "sleek-ui",
"version": "1.0.0",
"description": "Lightweight SASS and JS library for common UI elements",
"main": "dist/sleek-ui.js",
"sideEffects": false, // NOTE: Added this from Abhishek's article but it changed nothing for me :/
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --mode production"
},
"repository": {
"type": "git",
"url": "git+https://github.com/powerbuoy/sleek-ui.git"
},
"author": "Andreas Lagerkvist",
"license": "GPL-2.0-or-later",
"bugs": {
"url": "https://github.com/powerbuoy/sleek-ui/issues"
},
"homepage": "https://github.com/powerbuoy/sleek-ui#readme",
"devDependencies": {
"@babel/core": "^7.8.6",
"@babel/preset-env": "^7.8.6",
"babel-loader": "^8.0.6",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11"
},
"dependencies": {
"@glidejs/glide": "^3.4.1",
"normalize.css": "^8.0.1"
}
}
quelle
main
Attribut (Einstiegspunkt) in die package.json Ihrer Bibliothek eingefügt? Checken Sie Ihren Build ein. Und wie bündeln Sie Ihr lib-Paket?import { MyClass } from 'my-package/src/MyClass';
. Sie können auch die src-Build-Verpackung entfernen, um den Dateipfad zu verkürzen.Antworten:
Ja, Sie haben es so eingerichtet, dass jede Klasse in index.js importiert wird, die dann in eine Datei transpiliert wird (wenn sie auf ES5 abzielt, was am häufigsten vorkommt *). Dies bedeutet, dass diese Datei beim Import in eine andere Datei vollständig mit all diesen Klassen geliefert wird.
Wenn Sie das Baum richtig schütteln möchten, sollten Sie es nicht in ein CommonJS (ES5) -Bündel umwandeln. Mein Vorschlag ist, die ES6-Module entweder alleine oder an einem vom ES5-Bundle getrennten Ort aufzubewahren. Dieser Artikel soll Ihnen helfen, dies vollständig zu verstehen, und enthält empfohlene Anweisungen. Im Wesentlichen läuft es darauf hinaus, die Babel-Umgebung mit Preset-Env festzulegen (sehr zu empfehlen, wenn Sie es nicht bereits verwenden!), Um die ES6-Syntax beizubehalten . Hier ist die relevante Babel-Konfiguration, wenn Sie nicht auf ES5 transpilieren möchten:
Der Artikel beschreibt, wie Sie zwei Bundles einrichten, die jeweils eine andere Modulsyntax verwenden.
Ebenfalls erwähnenswert und wird auch im Artikel erwähnt. Sie können den Einstiegspunkt für das ES-Modul in package.json festlegen. Dadurch wird Webpack / Babel mitgeteilt, wo sich die ES6-Module befinden. Dies ist möglicherweise alles, was Sie für Ihren Anwendungsfall benötigen. Es scheint, dass konventionelle Weisheit sagt zu tun:
Die Knotendokumentation lautet jedoch wie folgt:
Wenn ich Zeit hätte, würde ich damit herumspielen und sehen, was richtig funktioniert, aber das sollte ausreichen, um Sie auf den richtigen Weg zu bringen.
* ES5-bezogene Bundles haben das CommonJS-Format, das alle zugehörigen Dateien enthalten muss, da ES5 keine native Modulunterstützung bietet. Das kam in ES2015 / ES6.
quelle
targets.esmodules: true
und während dies Änderungen am erstellten Skript vorgenommen hat, hat sich nichts daran geändert, was am Ende importiert wurde. Beim Importieren einer einzelnen Klasse aus wirdmy-package
weiterhin alles importiert. Ich habe auch die Änderungen inpackage.json
(zusammen mit der anderen Änderung) ausprobiert und auch das hat nichts geändert. Nun, das Hinzufügen hattype: module
meinen Build mit "Muss Import zum Laden des ES-Moduls verwenden: /sleek-ui/webpack.config.js require () von ES-Modulen wird nicht unterstützt." also musste ich das bisschen entfernen. Ich werde mir den verlinkten Artikel ansehen.modules: false
(nicht drinnentargets
), aber das hat auch nicht funktioniert ... Ich denke, ich werde einfach direkt aus der Quelldatei importieren und babel durch node_modules laufen lassen, bis wir dieses Zeug nativ verwenden können.import MyClass from 'my-package/myClass';
. Ein gutes Repo-Beispiel dafür ist lodash-es .Dies ist ein gültiger Anwendungsfall. Das ultimative Ziel ist es, dies zu tun,
import { MyClass } from 'my-package'
aber es gibt einen saubereren Weg, dies zu tun.Erstellen Sie eine Aggregator-Indexdatei in Ihrem
my-package
. Grundsätzlichmy-package/index.js
und es sollte so aussehen:Dann können Sie tun
import { MyClass } from 'my-package'
. Kinderleicht.Habe Spaß!
quelle