Prüfen ob Script als Module läuft
- javascript
Hallo,
ich möchte ein externes Script wahlweise per <script src="…"> oder per import einbinden. Für die import-Einbindung soll es im Script ein export geben. Dieses export liefert eine Fehlermeldung, wenn das Script nicht als module läuft.
Gibt es eine Möglichkeit, im Script abzufragen, ob es als Module läuft?
Ausprobiert habe ich console.log(typeof import.meta);, aber das liefert eine Fehlermeldung: SyntaxError: import.meta is only valid inside modules. Auch try-catch hilft hier nicht.
Gruß
Jürgen
Hallo Jürgen,
das geht nicht, denke ich. Sobald export im Script steht, bricht der normale Script-Loader ab. Chrome: "Unbekanntes Token", Firefox: "export darf nur auf Top-Level eines moduls stehen." Die FF Meldung gibt Dir schon den Hinweis auf das Grundproblem: export wird nur im Modul verstanden und ein bedingter Export ist syntaktisch verboten. Aber sowas müsstest Du tun, wenn Du außerhalb eines ES6-Modul-Kontextes eine alternative Einbindung anbieten möchtest.
Wie möchtest Du überhaupt den export ersetzen, wenn es kein ECMA-Script Modul ist?
Warum möchtest Du überhaupt den export ersetzen? Wenn dein Caller kein ECMA-Script-Modul ist, kann er dein Modul mit der import-Funktion einbinden und die exportierten Gerätschaften über das Modul-Objekt nutzen.
Wenn der Brauser deines Caller kein import() beherrscht, rate ihr/ihm zum Browser-Update. ECMAScript-Modulsupport würde ich heutzutage als Pflicht ansehen. Du kannst nicht unbedingt verlangen, dass dein Caller seinen Code als Modul schreibt (könnte man, muss man aber nicht), aber sein Browser sollte Module unterstützen. Andernfalls hast Du vermutlich ganz andere Probleme in diesem Uraltbrowser.
Ein Adapter-Script zwischenzuschalten, das den import()-Aufruf kapselt, kann funktionieren - muss aber nicht. Die import()-Funktion ist asynchron, man MUSS wissen, dass sie genutzt wird und darauf warten, dass sie fertig ist. Und du möchtest in deinem Adapter-Script sicherlich keine busy-loop laufen lassen, bis das Modul verfügbar ist.
Der Benutzer:
<script>
import("./jb_plotter.js").then(runMyCode);
function runMyCode(jbModul) {
const plotter = new jbModul.Plotter(myCanvas);
plotter.plot(x => x**2);
}
</script>
Dein jb_plotter.mjs:
export class Plotter {
constructor(canvas) {
...
}
plot(func) {
...
}
}
Rolf
Hallo Jürgen,
Onkel Claude hat mir gerade noch vorgeschlagen, in der package.json eine dualen Einstieg vorzusehen. Aber das setzt node.js als Infrastruktur voraus und ist vermutlich eher nicht der von Dir angestrebte Weg.
Er hat mir in dem Zusammenhang aber noch rollup.js vorgeschlagen. Das ist ein Bundler, der von Modul nach Klassikscript transpilieren kann. Damit könntest Du ohne viel Aufwand beide Formen anbieten.
Rolf
Hallo Rolf,
Onkel Claude hat mir gerade noch vorgeschlagen, in der package.json eine dualen Einstieg vorzusehen. Aber das setzt node.js als Infrastruktur voraus und ist vermutlich eher nicht der von Dir angestrebte Weg.
nein.
Er hat mir in dem Zusammenhang aber noch rollup.js vorgeschlagen. Das ist ein Bundler, der von Modul nach Klassikscript transpilieren kann. Damit könntest Du ohne viel Aufwand beide Formen anbieten.
das ist sowohl für meine "Kunden" als auch fürs Wiki zu kompliziert.
Gruß
Jürgen
Hallo Rolf,
das geht nicht, denke ich. Sobald export im Script steht, bricht der normale Script-Loader ab.
das habe ich befürchtet. Trotzdem vielen Dank für deine Mühe.
Z.Zt. erzeuge ich in den externen Scripten ein Objekt, z.B. SW.grafik und SW.plot, ich lege also alles in das globale Objekt SW. In meinen Scripten git es statt dessen ein globales JB. Und das möchte ich vermeiden. Für die Zeit der Umstellung wollte ich aber nicht zweigleisig fahren und daher das export hinter einer Abfrage verstecken.
Gruß
Jürgen
PS Wie ist denn der Stand beim neuen Frickl?
Hallo Jürgen,
Frickl schiebe ich vor mir her 😟
Aber wie gesagt: Mach ein ES6-Modul daraus. Exportiere grafik und plot. Der Klassik-User verwendet die import()-Funktion. Der ES6-User verwendet das import-Statement.
Natürlich sind grafik und plot dann keine globalen Variablen, aber wenn der User das WILL, kann er eine Variable SW anlegen und den Kram darin speichern. Muss aber nicht sein, statt dessen kann man alles in diese runMyCode-Funktion packen.
Rolf