Mendix ist die Low-Code-Plattform Nummer eins und eine ihrer wichtigsten Stärken ist die Erweiterbarkeit, die sie bietet. Sie können React verwenden, um coole Bibliotheken von Drittanbietern einzubinden und Ihre Anwendung zu erweitern.
Dies ist Blog 4 einer mehrteiligen Serie, die vorherigen Blogs finden Sie hier: Erstellen Sie Widgets in Mendix mit React — Teil 1 — Farbzähler, Erstellen Sie Widgets in Mendix mit React Teil 2 – Timerund Erstellen Sie Widgets in Mendix mit React Teil 3 – Kanban.
Was bauen wir
Kürzlich wurde gezeigt, dass Ivo Sturm hat einen Blog über die Konvertierung eines vorhandenen ArcGIS-Widgets von Dojo nach React geschrieben.
Ich dachte, es wäre interessant, Erstellen Sie eine einfache Version des ArcGIS-Karten-Widgets von Grund auf.

Los geht´s
Wie bei allen Pluggable-Widget-Blogs bis hierhin beginnen wir mit Gerüst unseres Widgets durch Laufen yo @mendix/widget arcGISMap und Einrichten eines Tests Mendix Projekt.
Beginnen wir mit Installieren des npm-Pakets für die ArcGIS Javascript API
npm install @arcgis/core
ArcGIS ist ein geografisches Online-Informationssystem, mit dem Sie Karten anzeigen und Ebenen hinzufügen können, um eine ganze Reihe von Informationen anzuzeigen.

Um den vollen Service nutzen zu können Sie müssen sich registrieren und einen Zugriffstoken erstellen Für unser einfaches Beispiel können wir aber auch ohne eines weitermachen.
Erste Schritte
Überprüfung der Dokumentation Wir können unseren Code aktualisieren, um zwei Dateien zu haben:
Ein Elternteil
importiere { ReactElement, createElement } von "react"; importiere { MapComponent } von "./components/Map"; importiere { ArcGISMapBlogContainerProps } von "../typings/ArcGISMapBlogProps"; importiere "./ui/ArcGISMapBlog.css";
Exportfunktion ArcGISMapBlog(Eigenschaften: ArcGISMapBlogContainerProps): ReactElement { return ; }
Und ein Kind
importiere { ReactElement, createElement, useEffect, useRef } von "react"; importiere Map von "@arcgis/core/Map"; importiere MapView von "@arcgis/core/views/MapView"; Legende importieren von "@arcgis/core/widgets/Legende";
Exportschnittstelle MapProps { Basiskarte: Zeichenfolge; }
Exportfunktion MapComponent({ basemap }: MapProps): ReactElement { const mapDiv = useRef(null);
useEffect(() => { if (mapDiv.current) { MountMap(Basiskarte); } }, [Basiskarte]);
const MountMap = (Basiskarte: Zeichenfolge): MapView => { const legend = neue Legende(); const map = neue Map({ Basiskarte }); const view = neue MapView({ Karte, Zentrum: [0.029, 51.256], // Längengrad, Breitengrad Zoom: 10, // Zoomstufe Container: mapDiv.current als unbekanntes HTMLDivElement });
legend.view = Ansicht; view.ui.add(legend, "unten rechts"); Ansicht zurückgeben; };
zurückkehren ; }
Lass uns Importieren Sie auch das Stylesheet aus ArcGIS Damit unser Widget gut aussieht, ändern Sie Ihre UI/{widgetName}.css in:
@import "https://js.arcgis.com/4.24/@arcgis/core/assets/esri/themes/dark/main.css";
Nun bauen wir unser Widget mit npm run build und… wir erhalten eine Fehlermeldung:
[!] Fehler: Ungültiger Wert für Option „output.file“ – beim Erstellen mehrerer Chunks muss die Option „output.dir“ verwendet werden, nicht „output.file“. Um dynamische Importe einzubinden, setzen Sie die Option „inlineDynamicImports“.
Wie können wir das also beheben? Um das zu erklären, müssen wir ein paar Schritte zurückgehen …
Eine kurze Geschichte von Javascript
Im nächsten Abschnitt finden Sie eine kurze Geschichte von Javascript, um der Lösung einen Kontext zu geben. Wenn Sie daran nicht interessiert sind, können Sie es überspringen und mit dem Beispiel fortfahren.
Am Anfang…
Javascript wurde 1995 von Brendan Eich erfunden und in den ersten Jahren seiner Entwicklung hauptsächlich für isolierte Skriptaufgaben verwendet. Als JS zunehmend in Anwendungen verwendet wurde, wurde es schwieriger, den Code zu verwalten. JS wurde auf komplexere Weise verwendet, oft über mehrere Skripte hinweg, was unvermeidlich zu Funktions- und Namenskonflikten führte.
Aus diesem Grund wurde das Modulkonzept eingeführt. Dies bedeutete, dass Code an einem geschlossenen Ort für den internen Gebrauch geschrieben werden konnte, ohne dass Konflikte an anderer Stelle befürchtet werden mussten. Außerdem konnten Entwickler große Codebasen in kleine separate Teile aufteilen, was das Schreiben und Warten erheblich vereinfachte.
Der erste Versuch, dies zu beheben, erfolgte mit Sofort aufgerufene Funktionsausdrücke (IIFE), das im Wesentlichen einfach jede Datei in eine Funktion einschloss und Variablen und Funktionen innerhalb einer Datei in diesem Gültigkeitsbereich statt im globalen Gültigkeitsbereich behielt.
(function() {// Your code }) ();
Es gibt noch viele Probleme mit diesem Ansatz, darunter eine fehlende Abhängigkeitsauflösung und Verschmutzung des globalen Namensraums.
Im Laufe der Zeit entstanden drei separate (und konkurrierende) Modulspezifikationen:
- CommonJS — wird in Node immer noch häufig für serverseitiges JS verwendet und ist leicht an seinem
require()undmodule.exportsSyntax - AMD – Asynchrone Moduldefinition, wurde schon früh von CommonJS abgespalten. Der Hauptunterschied besteht darin, dass AMD das asynchrone Laden von Modulen zulässt, die nicht voneinander abhängig sind (der Name sagt alles!)
- UMD — Universal Module Definition, unterstützt sowohl die anderen Modulspezifikationen als auch die „globale“ Variablendefinition im alten Stil
Das ist alles sehr kompliziert … aber es gibt gute Neuigkeiten. Seit 2015 und der Veröffentlichung von ES6 Module wurden innerhalb der Javascript-Sprache unterstützt. Dies gibt uns die schöne und einfacheimport und export Syntax, die wir in unserem Code verwendet haben.
Warum also diese Geschichtsstunde? Nun, wir müssen in der Lage sein, alle diese Modultypen zu verarbeiten, wenn wir unseren Code schreiben, und hier kommen die Bundler ins Spiel.
Bündeler
Mit Bundlern können Sie Kompilieren Sie Ihren Code zur Build-Zeit, Verarbeiten Sie Ihre Abhängigkeitenund eine kompatible zusammengesetzte Datei bereitstellenGängige Lösungen hierfür sind Webpack (benutzt in Mendix 8 Widgets) und aufrollen (benutzt in Mendix 9 Widgets)
Auf diese Weise können Sie Ihren Code mithilfe moderner ES6-Funktionen (und sogar Typescript, wenn Sie Lust dazu haben) modular schreiben und dann eine optimierte Datei (oder einen Satz von Dateien) erstellen, die dem Browser bereitgestellt wird.
Das ist großartig, aber einige Browser unterstützen ES6 noch nicht, sodass sie mit diesen schön kompilierten Dateien nichts anfangen können. Um dies zu beheben Wir können einen Transpiler verwenden wie Babel um es der Webseite in einem lesbaren Format bereitzustellen.
Also zurück zu unseren Widgets …
Das Pluggable Widget-Framework erfordert alle Tools, die Sie zum Entwickeln von React-Komponenten benötigen für Mendix Apps. Dazu gehören:
- npm — Ein Paketmanager zur einfachen Installation und Verwaltung von Drittanbieterpaketen
- aufrollen — Ein Bundler, mit dem Sie Ihren Code modular schreiben und dann in kleinen Paketen bündeln können
- babel — Ein Transpiler, der das JS in ein Format konvertiert, das von älteren Browsern (und Studio Pro) gelesen werden kann
Was bedeutet also unser Fehler?
[!] Fehler: Ungültiger Wert für Option „output.file“ – beim Erstellen mehrerer Chunks muss die Option „output.dir“ verwendet werden, nicht „output.file“. Um dynamische Importe einzubinden, setzen Sie die Option „inlineDynamicImports“.
Für jedes Widget-Projekt verwenden wir die Rollup-Konfiguration, die von der Bibliothek @mendix/pluggable-widget-tools bereitgestellt wird.
Diese finden Sie in: node_modules/@mendix/pluggable-widget-tools/configs.rollup.config.js.
In dieser Konfiguration sind wir Sagen Sie unserem Widget, dass es unser kompiliertes JS in eine einzelne Datei ausgeben soll. Inzwischen ist die ArcGIS npm-Bibliothek wir verwenden bietet dynamische Importe in Blöcken, die standardmäßig rollup will als separate Dateien in ein Verzeichnis ausspucken.
Um dies zu beheben, müssen wir nur tun, was in der Fehlermeldung steht und Legen Sie die Option inlineDynamicImports fest., wodurch alles in eine Datei gezogen wird. Wir könnten die Datei rollup.config.js in der Pluggable Widgets-Bibliothek ändern, aber das ist keine gute Idee, da sie nicht wartbar ist und sehr schwer zu lesenden und zu debuggenden Code erzeugt. Glücklicherweise Mendix verfügt über eine integrierte Funktion zum Festlegen unserer eigenen Rollup-Konfiguration.
Wir müssen eine Datei erstellen genannt rollup.config.js im Stammverzeichnis des Widgets. Anschließend fügen wir den folgenden JS-Code hinzu, um die Erstellung unseres Widgets zu ändern:
export default args => { const result = args.configDefaultConfig; console.warn ('Benutzerdefiniertes Rollup') return result.map((config) => { config.output.inlineDynamicImports = true console.warn ("Dynamische Importe festlegen") return config; }); };
Also rennen wir npm run build erneut und erhalte einen neuen Fehler:
SCHWERWIEGENDE FEHLER: Heap-Limit erreicht. Zuordnung fehlgeschlagen – JavaScript-Heap nicht genügend Arbeitsspeicher
Es stellt sich heraus, dass der Build-Prozess mehr Speicher benötigt. Ich kann dies aktualisieren, indem ich ausführe
export NODE_OPTIONS=--max_old_space_size=5120
Wenn wir neu erstellen, wird unser Widget jetzt kompiliert.
Unser Bundler kann uns dabei helfen, einzelne Dateien so zu erstellen, dass sie problemlos vom Browser gelesen werden können.
Rollup bietet außerdem noch etwas sehr Cleveres: Baum zittert: Dabei geht es um den Aufbau eines Bildes der Abhängigkeitsbaum in Ihrem Code und nur den Code einbinden, der tatsächlich benötigt wird. Dies ist besonders nützlich, wenn große Bibliotheken verwendet werden, und vermeidet das Laden großer Mengen ungenutzten Codes in den Browser. Dieses Tree Shaking ist einer der Schlüsselfaktoren Mendix habe den Wechsel von Webpack zu Rollup zwischen Mendix 8 und 9.
Bundler bieten außerdem eine ganze Reihe weiterer Funktionen, im Rollup sind diese in Form von Plugins verfügbar. Als letztes möchte ich in diesem Blog einen sehr häufigen Anwendungsfall behandeln, bei dem Sie Ihre Rollup-Konfiguration für Ihr Widget ändern müssen.
Bereitstellung der Dateien, die Ihr Widget benötigt
ArcGIS stellt die für die Erstellung Ihrer Karte erforderlichen Dateien über eine Content Delivery Network (CDN) Es kann jedoch Fälle, in denen Sie und verwalten Sie diese Dateien in Ihrem Widget, möglicherweise aufgrund von Firewall-Einstellungen in Ihrer Organisation. Glücklicherweise macht die ArcGIS Javascript API dies möglich.
Als erstes müssen wir unseren Code aktualisieren, um Informieren Sie die API dass wir sein werden Verwaltung unserer Vermögenswerte vor Ort. Dazu aktualisieren wir einfach unsere Containerkomponente, sodass sie Folgendes enthält:
importiere esriConfig von "@arcgis/core/config.js";
Exportfunktion ArcGISMapBlog (Eigenschaften: ArcGISMapBlogContainerProps): ReactElement { esriConfig.assetsPath = "./widgets/mendix/arcgismapblog/assets"; Rückgabe ; }
Als nächstes müssen wir Aktualisierung UNSERE aufrollen zu holen Sie die Dateien ab, die wir brauchen von unseren Node-Modulen und füge sie in unser Widget ein mpk.
Dazu können wir Verwenden Sie das Rollup-Kopier-Plugin (es gibt Plugins für alles), zuerst müssen wir es installieren
npm i rollup-plugin-copy —save-dev
Wir nutzen die —save-dev Befehl, da es sich um eine Abhängigkeit handelt, die nur während der Entwicklung benötigt wird. Dann aktualisieren wir unsere rollup.config.js wie folgt:
importiere Kopie von „Rollup-Plugin-Copy“; exportiere Standardargumente => { const Ergebnis = args.configDefaultConfig; console.warn („Benutzerdefiniertes Rollup“) returniere Ergebnis.map((Konfiguration) => { config.output.inlineDynamicImports = true console.warn („Dynamische Importe festlegen“) const Plugins = config.plugins || [] config.plugins = [ …Plugins, Kopie({ Ziele: { src: „node_modules/@arcgis/core/assets“, dest: „dist/tmp/widgets/mendix/arcgismapblog“ }]
}), ] Konfiguration zurückgeben; }); };
Dieser nimmt das "Vermögen" Ordner aus dem ArcGIS npm-Paket und legt es in unserem dist/tmp-Ordner ab das ist, was letztendlich komprimiert wird, um unser mpk zu erstellen. Wenn wir dann unsere Anwendung ausführen, wird der Inhalt des Widgets mpk bereitgestellt an ./widgets/{IhrOrganisationsname}/{IhrWidgetname}.
Um dies in Aktion zu sehen, führen wir den Befehl zum Erstellen unseres Widgets aus
npm run build
Wir können unsere App dann erneut ausführen.

Wenn wir unser Bereitstellungsverzeichnis öffnen, können wir sehen, dass das Widget den Assets-Ordner bereitstellt, und wenn wir unsere Seitenquellen in unseren Chrome-Entwicklertools überprüfen, können wir sehen, dass die ArcGIS-Web-Assembly-Datei an den Browser übermittelt wird, um sicherzustellen, dass unsere Karte funktioniert.
Wir haben unser CSS nicht aktualisiert, um lokale Dateien zu verwenden. Dazu aktualisieren wir einfach unsere Datei wie folgt:
@import "../assets/esri/themes/dark/main.css";
Einfach….irgendwie….
Wenn Sie das verwenden Pluggable Widget Tools von 9.13.2 oder niedriger und Sie verwenden Windows, dann Schriftarten werden nicht richtig importiertUm die Importe zu korrigieren, ist der folgende Code in Ihrer rollup.config.js erforderlich:
importiere postcssUrl von „postcss-url“;
const cssUrlTransform = asset => { const outWidgetDirForwardSlash = outWidgetDir.replace(/\\/g, "/") return asset.url.startsWith(`${assetsDirName}/`) ? `${outWidgetDirForwardSlash}/${asset.url}` : asset.url; }
export default args => { const result = args.configDefaultConfig; console.warn ('Benutzerdefiniertes Rollup') return result.map((config) => { config.output.inlineDynamicImports = true console.warn ("Dynamische Importe festlegen") const plugins = config.plugins || [] config.plugins = [ ...plugins, postcssUrl (cssUrlTransform)
] Konfiguration zurückgeben; }); };
Dann renne npm install postcss-url --save-dev . Ihr Widget wird jetzt mit Symbolen gerendert.
Und wir sind fertig!
Die ArcGIS API ist vollgepackt mit tollen Funktionen, ich möchte Sie ermutigen, sie zu erkunden. Ein tolles Beispiel dafür, was sie kann, finden Sie im Widget von Ivo Sturm: GitHub – ivosturm/ArcGIS-React: Ein neues und verbessertes ArcGIS-Widget basierend auf React. Das Repo für mein ArcGIS-Widget finden Sie hier: GitHub – joe-robertson-mx/arcGISMapBlog.