• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Probleme beim Einstieg in Module

Sclero2004

Mitglied
Ich versuche gerade, einen Einstieg in die Module und das Packaging bei Javascript zu finden und komme nicht voran. Ein erstes Einzelproblem habe ich bei Stackoverflow gepostet aber leider keine Antwort:
Wenige Kommentare, die sagen, warum es nicht geht aber keine Lösung wie es richtig ist.
Würde mir da jemand weiter helfen und zunächst die Frage dort beantworten?
Mit den Modulen werde ich bei Electron und Capacitor konfrontiert, dort geht es offenbar nicht ohne und auch nicht ohne Packaging.
Beste Grüße, Ulrich
 

AndreasB

Mitglied
Ich versuch's mal

Die erste Antwort in Stackoverflow sagt ja schon, dass du zwei Konzepte mischst:
CommonJS
Javascript:
// export.js
module.exports = 42;

// import.js
const mol = require("./file1.js")
Das Modulsystem, dass vor Allem in Node.js angewandt wird.

und

esm (ECMA Script Mudules)
Javascript:
// export.js
export const mol = 42;

// import.js
import { mol } from "./file1.js"
Das einzige Modulsystem, dass nativ in JavaScript eingebaut ist und auch von Browsern unterstützt wird.

Wenn man es ganz genau nimmt, verwendest du gar nicht Common.JS, sondern implementierst einen „Polyfill“, der von Bundlern verwendet wird und im Browser so nicht funktionieren wird.

Mein Vorschlag:
werfe den "Polyfill Code" weg und verwende
Javascript:
// export.js
export const isEven = function (x) {
  return x % 2 === 0;
};
(Dies muss in einer eigenen Datei sein. Aus einem Script-Tag kann man - soweit ich das weiß - nichts exportieren.)

und importier' es mit:
HTML:
<script type="module">
   import { isEven } from "./export.js";
/...
</script>

So kannst du dich mit der Syntax vertraut machen.


Ich hoffe das hilft dir.
 

Sclero2004

Mitglied
Vielen Dank, das sind schon Mal sehr wertvolle Infos.
Das Problem stellt sich für mich nur bei Capacitor (bei Electron kann ich die vorgegebenen Module problemlos importieren.)
Bei der Verwendung von Plugins habe ich ein Verzeichnis node_modules wo die Dateien dieser Plugins drin sind. Und diese will ich irgend wie einbinden ohne sie manuell editieren zu müssen. (Mit um editieren habe ich es hin bekommen, ist aber unschön.)
Aus dem Verzeichnisnamen leite ich ab, dass es sich um Node-Module handelt, d. h. die Hinweise in deinem ersten Textblock treffen zu.
Nach deinen Aussagen in deinem zweiten Textblock wird jedoch nur der Import von ESM-Modulen durch die Browser unterstützt. Und mir scheint, dies ist genau die Ursache meines Problems, ich will/muss Node-Module im Browser importieren.
Ich dachte, dies könne über das Bundling gelöst werden und habe zunächst Browserify verwendet, aber ohne richtigen Erfolg. Nächster Versuch war dann NX wo ich beim Lesen der Startseite schon den Eindruck gewann, dass es sehr mächtig und ein Overkill für mein Vorhaben ist. Und wie man bei Stackoverflow sieht, bin ich schon bei einem sehr einfachen Einstieg gescheitert.
Trifft denn der Ansatz zu, dass ich den Import von Node-Modulen im Browser über ein Bundling lösen kann?
Beste Grüße, Ulrich
 

Sclero2004

Mitglied
PS, Ich vergaß: Da es um das Importieren von Node-Modulen geht, die ich nicht ändern will, ist dein Vorschlag am Schluss wahrscheinlich nicht anwendbar?
 

AndreasB

Mitglied
PS, Ich vergaß: Da es um das Importieren von Node-Modulen geht, die ich nicht ändern will, ist dein Vorschlag am Schluss wahrscheinlich nicht anwendbar?
Das hast du richtig erkannt.

Der node_modules Ordner enthält alle Module die über npm geladen wurden. Das Verwendete Modulsystem bei einem Plugin ist dem Autor des jeweiligen Moduls überlassen.
Leider kann man dem Modul selten ansehen, mit welchem es erstellt wurde und muss sich erstmal die Dokumentation anschauen.

Capacitor ist ein framework für hybride Apps und in der Regel nicht für browser Apps. (Oder meinst du diesen Ansatz: https://capacitorjs.com/docs/web? Damit habe ich noch keine Erfahrungen gemacht.)
Capacitor verwendet das esm System und da es seine eigene CLI hat, muss man sich um das Bundeln nicht selber kümmern.

Wo musst du denn node_modules im Browser importieren? Die Idee mit dem Bundeln ist auf jeden fall schonmal gut, browserify ist aber eine ziemlich alte Lösung.
Nx kenne ich persönlich nicht, sieht mir aber für das reine Bundeln zu komplex aus.
Ich würde dir mal vite oder esbuild empfehlen, aber nicht für Capacitor, da verwende die CLI.

Wenn ich dir damit nicht helfen konnte, schilder doch nochmal, was du genau vorhast und um welche Module es sich handelt.
 
Zuletzt bearbeitet:

Sclero2004

Mitglied
Danke erneut für diese Hinweise.

Was die Module in node_modules betrifft hatte ich die naive Vorstellung, dass ein Werkzeug existiert, das mir diese Module, möglicher Weise durch Bundling, so aufbereitet, dass ich sie im HTML einbinden oder importieren kann. Wahrscheinlich zu optimistisch gedacht?

Genau den und nach dieser Anleitung bin ich vor gegangen um das Ganze aufzubauen. Die Anleitung unter "Using Capacitor as a Script Include" liefert zwar genau was ich brauchte, hat aber zwei Nachteile:
  1. Sie wird als "deprecated" gekennzeichnet und am Schluss funktionierte sie überhaupt nicht mehr.
  2. Sie deckt die zusätzlichen Module bzw. Erweiterungen nicht ab, die ich aber irgend wie auch einbinden muss.
Ich fand es zunächst voll genial, dass ich mit Capacitor und HTML, CSS, JS eine Android-App bauen kann ohne in Java etc. einsteigen zu müssen. Allerdings ist das anscheinend nicht der Kern von Capacitor und das würde erklären, dass es ein wenig stiefmütterlich behandelt wird und für meine Probleme so wenig zu finden ist.

Noch eine Frage zu den Innereien der Module. Ich finde da Code nach folgendem Muster:
Code:
    exports.Filesystem = Filesystem;
    exports.FilesystemDirectory = FilesystemDirectory;
    exports.FilesystemEncoding = FilesystemEncoding;
    window.exportsFs = exports; // <---
    Object.defineProperty(exports, '__esModule', { value: true });
    return exports;
})({}, capacitorExports);
//# sourceMappingURL=plugin.js.map
(die Erweiterung für Filesystem, ganz am Ende)
Die Zeile mit dem Pfeil habe ich hinzu gefügt, um die Variable "exports" global zu machen. Auf die Weise funktioniert es aber vom Handling her nicht gut weil ich jedes Mal die Datei anfassen muss und sauber kommt es mir auch nicht vor (obwohl es irgend wo so empfohlen wurde).
Wo ist denn dieses Muster einzuordnen?
 

Sclero2004

Mitglied
PS: Mir scheint, jetzt klärt sich das Ganze ein wenig. Der Beginn der Javascript-Datei von vorhin sieht so aus:
Code:
var capacitorFilesystem = (function (exports, core) {
    'use strict';
und dann wird ein Schuh daraus: Die anonyme Funktion gibt das Objekt "exports" zurück und weist sie der Variablen capacitorFilesystem zu. D. h. sie tut genau das, was ich zuvor durch mein Editieren gemacht hatte. Wenn ich mir das in der Console ansehe, voila, finde ich genau diese Variable global vor mit den Funktionen darin und kann damit arbeiten. Offenbar gewinne ich auf diese Weise Zugriff auf die Module mit ihren Funktionen.
Dass das nirgend wo erklärt wird, liegt möglicher Weise daran, das die Weise wie ich Capacitor benutze, nur ein Nebenschauplatz ist?
 

AndreasB

Mitglied
Wahrscheinlich zu optimistisch gedacht
Eigentlich nicht, denn genau solche Werkzeuge existieren. Viele modernen Bundler können einen commonJS import verstehen. Oder auch commonJS Module an die esm syntax anpassen.
Was beim Bundeln zum Schluss herauskommt ist meinst eine einzige .js Datei, die allen Code enthält und der ganz normal in HTML eingebunden werden kann.
Oben habe ich ja schon vite erwähnt, falls du ein komplettes Tooling benötigst. Oder esbuild falls du nur ein Buildtool brauchst.

Nochmal ein Wort zu Capacitor:
Der Usecase von Capacitor ist es eine Codebasis für Android und iOS Apps zu haben und so wenig wie möglich nativen Code schreiben so müssen (meinst kommt man nicht komplett ohne nativen Code aus). Was dabei heraus kommt ist ein Warpper um eine Native WebView. Die App läuft somit auf dem Mobilen Gerät als Webapp im Fullscreen-Browser.
Damit ist es eine App, die man ganz normal in dem App/Play-Store platzieren kann.
Dabei stellt Capacitor das Tooling und die Communikation mit den nativen Plattformen. Das Ionic-Framework Stellt die Komponenten und das Styling für Nativ-wirkende Komonenten.
(Eventuell hat ionic was du benötigst?)
Dieser Ansatz wird oft von Firmen verwendet, die eine App in den App/Playstore stellen wollen, aber Entwicklungs- und Maintenance Kosten sparen wollen.

Dass das nirgend wo erklärt wird, liegt möglicher Weise daran, das die Weise wie ich Capacitor benutze, nur ein Nebenschauplatz ist?
Ich denke damit hast du recht. Ich habe ja kurz den Usecase für Capacitor dargestellt.
Wenn es dir nicht um den hybriden Teil von Capacitor geht, sondern nur um den PWA Teil, würde ich auf Capacitor komplett verzichten und die eventuell sowas wie das vite-pwa-plugin verwenden. Oder - je nach Usecase - komplett auf ein Plugin verzichten.
 

Sclero2004

Mitglied
Bevor ich da mit dem Bundling einsteige, noch eine andere Frage: Ich habe jetzt 4 Apps und es wird wahrscheinlich noch eine dazu kommen. Und recht viel von dem Javascript was ich selbst entwickelt habe, ist bei allen gleich. D. h. es müsste eine Art Library her wo diese Skripts zentral abgelegt werden und auf die Zielverzeichnisse verteilt. Wird so etwas auch von einem Bundling-Tool unterstützt?
Der Weg, es selbst zu machen, wäre, die Dateien zentral abzulegen und mit einem kleinen Python-Skript auf die Zielverzeichnisse zu verteilen. Nicht kompliziert und einen anderen Weg möchte ich nur nehmen, wenn es ähnlich einfach wäre.
 

AndreasB

Mitglied
Für Shared Code gibt es viele Ansätze. Ein zentrales Verzeichnis, das als Dependency hinzugefügt wird, ist nur eine der Möglichkeiten.
Womit ich gute Erfahrungen gemacht habe, ist die Module als npm Packages abzuspeichern (es reicht wenn sie eine package.json haben und mit git versioniert werden) und diese über npm verwalten zu lassen.
Die Module können dann ganz einfach wie jedes andere npm Module auch importiert werden.
Ein weiterer Vorteil ist es, dass die Module durch git versioniert werden können und jede alte Version verwendet werden kann.
Wenn du die Packages nicht in das npm Repository laden möchtest, können diese Packages auch lokal auf der Platte liegen und von dort aus geladen werden. Außerdem kann man sie auf GitHub o.ä. hosten und von dort aus laden.
 
Oben