Der neue Dino in der Webwelt

Deno – Neue Runtime für serverseitiges JavaScript
Keine Kommentare

In seinem Vortrag „10 Things I Regret About Node.js“ hat Ryan Dahl, der Schöpfer von Node.js, von falschen Designentscheidungen gesprochen, die seinerzeit bei der Entwicklung von Node.js getroffen worden seien. Da man die Zeit nicht zurückdrehen kann, hat Dahl sein neues Projekt Deno ins Leben gerufen. Das Ziel: Schwächen von Node sollen revidiert und eine moderne, sichere Plattform für serverseitiges JavaScript bereitgestellt werden. Ist der Versuch geglückt?

Manchmal haben Produkte Erfolg, obwohl sie nicht perfekt sind und zahlreiche Fehler aufweisen. Ein Paradebeispiel ist JavaScript, eine Skriptsprache, die weit entfernt ist von technischer Exzellenz und elegantem Sprachdesign. Dennoch ist JavaScript mit eine der weltweit meist verwendeten Sprachen. Ähnliches gilt auch für Node.js, die serverseitige JavaScript-Plattform, die primär in Web- und Kommandozeilenapplikationen zum Einsatz kommt. Node.js-Entwickler Ryan Dahl hat nun ein neues Projekt ins Leben gerufen: Deno. Es soll von den Erfahrungen mit Node.js profitieren und eine neue, sichere Plattform sein. Auch in Deno werden Applikationen weiterhin in JavaScript beziehungsweise TypeScript implementiert – allerdings ändern sich einige Dinge grundlegend im Vergleich zur Entwicklung mit Node.js. Eine Gegenüberstellung der beiden Plattformen wäre allerdings nicht gerecht, da sich Deno aktuell noch in einer sehr frühen Phase befindet und sich sowohl die Schnittstellen als auch einige Architektur- und Designentscheidungen ändern können. Aus diesem Grund werfen wir einen Blick auf die Aspekte von Deno, die sich von Node unterscheiden, und zeigen, wie sich diese Unterschiede auf die tägliche Arbeit auswirken.

Was macht Deno besser als Node?

Die Idee hinter Deno ist dieselbe wie bei Node: Es soll eine Plattform zur Ausführung von JavaScript abseits vom Browser bieten. Wie bei Node ist auch Deno keine vollständige Eigenimplementierung, sondern bedient sich bei verschiedenen, bereits bestehenden Projekten. So kommt für JavaScript die Google Engine V8 zum Einsatz. Diese etabliert sich zunehmend zum Standard, wenn es um die Ausführung von JavaScript in verschiedenen Umgebungen geht. Browserseitig ist V8 sowohl in Chrome als auch mittlerweile in Edge integriert. Serverseitig setzen sowohl Node als auch Deno auf diese Engine. Im Gegensatz zu Node, dessen Kern in C++ geschrieben ist, nutzt Deno Rust als Programmiersprache. Rust wurde von Mozilla Research entwickelt und soll eine bessere Sicherheit als C++ beim Speicherzugriff bieten, bei einer ähnlich guten Performance. So ist es auch nicht verwunderlich, dass eines der zentralen Elemente, der Event Loop von Deno, in Rust implementiert wurde. Mit Rusts asynchroner Laufzeit Tokio hat Ryan Dahl auch hier auf ein bereits etabliertes Projekt zurückgegriffen.

Angular Camp 2020

Als Online- oder Präsenztraining!

Das 360°-Intensivtraining mit Angular-Koryphäe Manfred Steyer
Präsentiert von Entwickler Akademie

Sicherheit und Ressourcenzugriff

Einer der größten Kritikpunkte an Node sind Sicherheitslücken bei der Ausführung. Im Browser wird JavaScript in einer Sandbox ausgeführt, sodass in der Regel kein Schaden am System entstehen kann. Im Fall von Node ist die Situation anders: Eine Node-Applikation kann mit den Berechtigungen des Benutzers, der die Applikation gestartet hat, mit dem System interagieren. In erster Linie bedeutet das, dass die Applikation auf dasselbe Dateisystem wie der Benutzer zugreifen darf. Dieser Praxis schiebt Deno in seiner Standardkonfiguration einen Riegel vor und verbietet grundsätzlich den Zugriff auf das System. Erst nachdem der Benutzer den Zugriff erlaubt hat, kann die Applikation die Ressourcen verwenden. Deno geht damit wieder einen großen Schritt in die Richtung, Applikationscode in einer gesicherten Sandbox auszuführen. Es besteht ebenfalls die Möglichkeit, Zugriffe auf bestimmte Ressourcen on Demand oder generell über Kommandozeilenoptionen zuzulassen. Solche potenziell sicherheitskritischen Ausbrüche aus der Sandbox geschehen dann allerdings bewusst und nicht mehr aus dem Quellcode heraus.

TypeScript-Unterstützung

Deno greift einen der wichtigsten Trends der letzten Zeit in der JavaScript-Entwicklung auf und unterstützt TypeScript nativ. Das bedeutet, dass kein zusätzlicher Compile-Schritt benötigt wird, um den TypeScript-Code der Applikation in JavaScript umzuwandeln und auszuführen. Es ist auch kein externes Paket wie ts-node erforderlich, das sich um den Compile-Prozess und die unmittelbare Ausführung kümmert.

Modulsystem

Ein wichtiges Feature von Node ist sein Modulsystem. Es ermöglicht das Laden von Dateien und das Einfügen von Quellcode in die Applikation. Node befindet sich aktuell in einer Transition vom CommonJS-Modulsystem zum JavaScript-Standardmodulsystem. Dieser Wechsel verläuft eher schleppend, da sich die Node-Entwickler durch die große Verbreitung der Plattform keine Breaking Changes leisten können. Deno ist dagegen zu einem viel späteren Zeitpunkt entstanden, daher kann die Laufzeit sofort mit der aktuellen Modulsyntax starten. Für Entwickler bedeutet dies, dass keine require- oder module.exports-Statements mehr geschrieben werden müssen, sondern direkt mit den import- und export-Schlüsselworten gearbeitet werden kann. Im Gegensatz zum CommonJS-Modulsystem, wo die Importe dynamisch aufgelöst werden, erfolgt dies in Deno in der Regel statisch. Ein weiterer Unterschied zu Node ist, dass beim Import die Dateiendung ebenfalls angegeben werden muss. Entwickler Ryan Dahl begründet dies mit dem Hinweis, dass Deno deutlich näher am Web angesiedelt sein solle, als es bei Node der Fall sei. Wird eine Ressource geladen, muss ihre Bezeichnung vollständig angegeben werden – dazu gehört auch die Endung des Dateinamens.

Ein Erfolgsfaktor von Node ist dessen Paketmanager npm. Zwar ist npm kein fester Bestandteil von Node, jedoch arbeitet das Modulsystem der Plattform direkt mit ihm zusammen. Die Pakete werden aus einem zentralen Repository bezogen, wobei die Hürde für neue Pakete sehr gering ist: Jeder registrierte Nutzer kann Pakete publizieren. Eine Qualitätssicherung oder Sicherheitsüberprüfung fehlt. Es besteht lediglich die Möglichkeit, schädliche Pakete zu melden, die dann gegebenenfalls aus dem Repository entfernt werden. Bei der Installation eines Pakets wird der Quellcode auf das lokale System heruntergeladen und in einem Verzeichnis mit dem Namen node_modules gespeichert. Deno kommt ohne einen zusätzlichen Paketmanager aus, da das Modulsystem in der Lage ist, Pakete über URLs oder Dateisystempfade aufzulösen und die erforderlichen Ressourcen herunterzuladen. Damit wird Deno sein eigener Paketmanager, der sich sehr nahe am JavaScript-Standard bewegt. Und auch das node_modules-Verzeichnis, das nach Angaben von Ryan Dahl nur eingefügt wurde, weil die Benutzer von Node es brauchten, fällt damit weg. Ebenso benötigt Deno keine package.json– oder package-lock.json-Datei, um die Abhängigkeiten einer Applikation festzuhalten.

Installation – wie kommt Deno auf mein System?

Deno ist ein experimentelles Projekt, das zeigen soll, wie eine JavaScript-Plattform implementiert werden kann. Der Fokus der Entwickler liegt aktuell auf der Sicherheit und der generellen Architektur und nimmt weniger Rücksicht auf die Massentauglichkeit. Wo Node einem Entwickler prominent auf der Webseite ein Installer-Paket bietet, verweist Deno auf Shellskripte oder den Paketmanager des Betriebssystems. Mehr Informationen zu den verschiedenen Arten der Installation finden sich unter [1], Tabelle 1 fasst die wichtigsten Installationsarten zusammen.

Umgebung Kommando
Shell curl -fsSL https://deno.land/x/install/install.sh | sh
Powershell iwr https://deno.land/x/install/install.ps1 -useb | iex
Homebrew brew install deno
Chocolatey choco install deno

Tabelle 1: Installation von Deno

Ob die Installation von Deno auf dem System erfolgreich war, lässt sich herausfinden, indem auf der Kommandozeile der Befehl deno –version eingegeben wird. Dieser gibt neben der installierten Version von Deno auch die Versionen von V8 und TypeScript aus. Neben der klassischen Installation auf einem System kann man auch auf ein Docker Image zurückgreifen und Deno in einem Container betreiben.

Ausführung von Deno

Deno kann auf zwei Arten verwendet werden: interaktiv als Shell oder mit einer Datei als Eingabe. Die interaktive Variante wird in der Regel für kleinere Experimente angewandt. Aktuell besteht noch das Problem, dass Deno Shell nur JavaScript und kein TypeScript akzeptiert – an einer Unterstützung für TypeScript wird jedoch bereits gearbeitet.

Bei der Ausführungsvariante, die wahrscheinlich deutlich häufiger Anwendung findet, wird der Name einer Datei an Deno übergeben. Im Unterschied zu Node kann dies auch eine TypeScript-Datei oder eine entfernte Ressource sein, die beispielsweise über HTTP adressiert wird. So kann das Hello-World-Beispiel in Deno mit folgendem Kommando ausführt werden: deno https://deno.land/std/examples/welcome.ts. Dieses Skript macht nichts weiter, als die Zeichenkette „Welcome to Deno springer_Dino_Emoji.jpg“ auf der Konsole auszugeben.

Die Arbeit mit Deno

Die Umgebung von Deno ist in mehreren Schichten aufgebaut. Da die Plattform auf der V8 Engine basiert, stehen die gewohnten JavaScript-Schlüsselworte zur Verfügung. So ist es möglich, Elemente wie beispielsweise promise, import, export und zahlreiche weitere direkt zu verwenden, ohne dass sie zuvor importiert werden müssen. Auch bekannte globale Funktionen, wie setTimeout oder setInterval, stehen in Deno zur Verfügung. Ebenso das console-Objekt.

Neben diesen Standardkonstrukten besitzt Deno ein globales Objekt mit dem Namen Deno. Mit seinen Eigenschaften und Methoden bildet es die Basis für jede Applikation, sei es ein einfaches Skript zur Automatisierung bestimmter Abläufe, eine Kommandozeilenanwendung oder ein Backend für eine Webapplikation. Mit dem Deno-Objekt kann man beispielsweise auf das Dateisystem zugreifen und Netzwerk-Sockets öffnen. Das bedeutet aber auch, dass die Methoden dieses Objekts die Schnittstelle zum System darstellen und somit entscheidend für die Sicherheit der Plattform sind. So kann man die open- und listen-Methode nutzen, um eine Datei beziehungsweise eine Netzwerkverbindung zu öffnen und damit aus der gesicherten Sandbox von Deno auszubrechen. Diese Ausnahmen müssen jedoch vom Ausführenden der Applikation aktiv bestätigt werden, sodass unbemerkte Angriffe von einer Applikation auf das System deutlich aufwendiger werden.

Basierend auf diesen Schnittstellen arbeiten weitere Module. Standardmodule werden direkt von Deno zur Verfügung gestellt, andere von der Community, die sich aktuell um Deno bildet. Ein Standardmodul ist an dem /std im Pfadnamen des Moduls erkennbar. Die Pakete werden in der Regel unter [1] gehostet. Standardmodule, wie das http-Modul finden sich unter [2], die stetig wachsende Sammlung der Module von Drittanbietern kann ebenfalls von [1] bezogen werden. Diese weisen generell das Namensschema https://deno.land/x/MODULE_NAME@BRANCH/script.ts auf. So kann etwa der PostgreSQL-Treiber für Deno mit dem URL https://deno.land/x/postgres/mod.ts eingebunden werden.

Zugriff auf das Dateisystem – eine Frage der Berechtigung

Das lokale Dateisystem des Systems, auf dem eine Applikation ausgeführt wird, eignet sich als Quelle von Informationen und zum Speichern von Daten. Der Dateisystemzugriff ist in der Regel nicht sonderlich performant, und auch ein wahlfreier Zugriff auf eine solche Ressource ist meist aufwendig, sodass für die Persistierung größerer Datenmengen in der Regel Datenbanken zum Einsatz kommen. Für Konfigurationen oder Ähnliches eignen sich Dateien allerdings durchaus. Den Zugriff auf das Dateisystem regelt Deno direkt und geht dabei einen Schritt weiter als andere Plattformen und Programmiersprachen. In der Regel hat eine Applikation die gleichen Berechtigungen auf das System wie der Benutzer, unter dem die Applikation ausgeführt wird. Deno unterbindet standardmäßig den Zugriff auf das Dateisystem, außer der ausführende Benutzer erlaubt dies explizit. In Listing 1 ist zu sehen, wie eine Datei mit Deno-Bordmitteln ausgelesen werden kann.


const { open, close, readAll } = Deno;
 
const decoder = new TextDecoder('utf-8');
const file = await open('./input.txt');
const content = decoder.decode(await readAll(file));
console.log(content);
close(file.rid);

Das Auslesen der Inhalte von Dateien kann in drei Abschnitte unterteilt werden: Die open-Methode öffnet die Datei, die readAll-Methode liest den Inhalt und die close-Methode schließt sie wieder. Die Schnittstellen von Deno arbeiten asynchron und basieren auf Promises. Mit der aktuellen Version der V8 Engine kann in der Applikation bereits Toplevel await eingesetzt werden, ohne dass eine async-Funktion verwendet werden muss. Der Rückgabewert der readAll-Methode ist jedoch nicht, wie zu erwarten wäre, eine Zeichenkette, sondern ein Objekt vom Typ Uint8Array. Um dieses in eine lesbare Zeichenkette umzuwandeln, wird eine Instanz der TextDecoder-Klasse benötigt. Der decode-Methode dieser Instanz wird der Rückgabewert von readAll übergeben, worauf der Inhalt der Datei ausgeliefert wird.

Für den Fall, dass der Quellcode aus Listing 1 in einer Datei mit dem Namen index.ts gespeichert und mit dem Kommando deno index.ts ausgeführt wird, wirft Deno eine PermissionDenied Exception. Der Grund hierfür ist, dass das Skript versucht, auf eine Ressource des Systems zuzugreifen und damit aus seiner Sandbox ausbricht. Das Problem kann behoben werden, indem das Skript mit der Option –allow-read ausgeführt wird. Hierbei gilt es zu beachten, dass mit dieser Aktion die Leseeinschränkung für das gesamte System aufgehoben wird und das Skript so die gleichen Leseberechtigungen besitzt wie der Benutzer, der das Skript ausführt. Ein besserer Lösungsansatz ist daher, dieser Option einen Verzeichnisnamen zu übermitteln. Damit hat die Applikation lediglich lesenden Zugriff auf dieses Verzeichnis, während das übrige System weiter geschützt bleibt. Neben der –allow-read-Option gibt es noch die –allow-write-Option, die analog für schreibende Zugriffe auf das Dateisystem funktioniert.

Einsatz der Standardmodule

Die Implementierung des Dateizugriffs aus Listing 1 wirkt etwas sperrig. Gerade Standardoperationen wie das Auslesen einer Datei sollten mit einem Einzeiler erledigt werden können. Hier kommen die Standardmodule von Deno ins Spiel, indem sie den Kern der Plattform um zusätzliche Funktionalitäten wie Dateisystemzugriffe oder HTTP- und WebSocket-Unterstützung erweitern. Die Standardmodule wurden einige Zeit lang in einem separaten Repository verwaltet, sind mittlerweile jedoch im Haupt-Repository von Deno integriert. Die Standardmodule werden, wie alle anderen Module auch, über einen URL eingebunden. Im Fall des Dateisystemmoduls lautet dieser URL https://deno.land/std/fs/mod.ts. Listing 2 zeigt den Quellcode, der mit Hilfe des fs-Moduls den Inhalt der Datei ausliest.


import { readFileStr } from 'https://deno.land/std/fs/mod.ts';
 
const content = await readFileStr('./input.txt', { encoding: 'utf-8' });
 
console.log(content);

Wie schon die Kernmethoden sind zahlreiche Methoden der Standardmodule als asynchrone Funktionen in Deno implementiert. Diese arbeiten durchweg mit Promises und nicht mit Callbacks. In diesem Beispiel kommt die readFileStr-Methode des fs-Moduls zum Einsatz. Sie akzeptiert als erstes Argument den Namen der Datei, die ausgelesen werden soll, und als zweites ein Konfigurationsobjekt, mit dem zum Beispiel das Encoding angegeben werden kann. Die Rückgabe ist ein Promise vom Typ String, auf dessen Auflösung mit dem await-Schlüsselwort gewartet werden kann. Auch bei dieser Variante des Auslesens einer Datei sollte die Leseberechtigung auf das Dateisystem beachtet werden. Wird bei der Ausführung des Quellcodes nichts weiter angegeben, schlägt das Skript fehl, da keine Berechtigung vorliegt. Bei der ersten Ausführung des Skripts erscheint die Meldung, dass die Datei kompiliert und eine Reihe von Dateien heruntergeladen wurde. Bei diesen Dateien handelt es sich um die Abhängigkeiten, die die Applikation zur Ausführung benötigt. Im aktuellen Beispiel werden diese durch das Dateisystemmodul und seine Abhängigkeiten dargestellt. Der Download erfolgt allerdings nur bei der ersten Ausführung. Die Dateien werden in einem lokalen Cache gespeichert, sodass bei allen weiteren Durchläufen der Download entfällt und die lokale Version der Datei verwendet werden kann. Mit der –reload-Option kann angegeben werden, dass alle oder nur bestimmte Abhängigkeiten erneut geladen werden sollen.

Webapplikationen mit Deno entwickeln

Das typische Beispiel für serverseitiges JavaScript ist die Implementierung eines Webservers in nur wenigen Zeilen Quellcode. In dieser Disziplin steht Deno Node in nichts nach. Mit dem HTTP-Standardmodul lässt sich auf einfache Art ein Webserver umsetzen, wie in Listing 3 zu sehen.


import { serve } from 'https://deno.land/std/http/server.ts';
 
const body = new TextEncoder().encode('Hello World\n');
const s = serve({ port: 8000 });
for await (const req of s) {
  req.respond({ body });
}

Das HTTP-Modul findet sich unter [2]. Es exportiert unter anderem die serve-Funktion, mit der ein HTTP-Server gestartet werden kann. Beim Aufruf wird dieser Funktion ein Konfigurationsobjekt übergeben, das beispielsweise die Portnummer definiert, an die der Server gebunden wird. Bei der Behandlung der eingehenden Requests beschreitet Deno im Vergleich zu Node wieder einen neuen Weg. Wo in Node der Webserver klassisch Event-basiert mit Callback-Funktionen implementiert war, arbeitet Deno mit einem asynchronen Iterator. Dabei wird eine for-Schleife implementiert, die bei jeder eingehenden Anfrage erneut durchlaufen wird, wobei die req-Eigenschaft dabei für die Anfrage steht. Über dieses Objekt kann auf die verschiedenen Aspekte der Anfrage zugegriffen und mit req.respond die Antwort an den Client gesendet werden. Der Body der Nachricht wird als Uint8Array versendet, was mit Hilfe einer Instanz des TextEncoders und der encode-Methode erzeugt werden kann. Wie schon beim Zugriff auf das Dateisystem ersetzen die typisierten Arrays, die nativ in JavaScript implementiert sind, die Buffer-Objekte, die in Node zum Austausch von Binärdaten in einer Applikation zum Einsatz kommen. Wie im vorherigen Beispiel wird zunächst der Quellcode kompiliert, danach werden die Abhängigkeiten heruntergeladen. Anschließend bricht das Skript mit dem Fehler PermissionDenied ab. Das Öffnen einer Netzwerkverbindung gilt, wie schon der Zugriff auf das Dateisystem, als Verletzung der Sandbox, in der die Deno-Applikation ausgeführt wird. Damit der Webserver betrieben werden kann, muss die –allow-net-Option beim Ausführen der Applikation angegeben werden. Anschließend startet der Server und man kann mit dem Browser über http://localhost:8000 darauf zugreifen und erhält die Zeichenkette „Hello World“ als Antwort.

Web Application Frameworks für Deno

Eines der erfolgreichsten Projekte, das auf Node basiert, ist das Web Application Framework Express. Es ist einer der Gründe für den Erfolg von Node im Bereich von Webapplikationen, da es dem Programmierer zahlreiche Standardaufgaben abnimmt, damit er sich auf das Wesentliche, nämlich die Businesslogik der Applikation, konzentrieren kann. Ähnliche Projekte existieren auch für Deno. Es ist also nicht erforderlich, dass Features wie beispielsweise Routing, also die spezifische Behandlung angefragter URL-Pfade, implementieren werden müssen. Eine Liste der aktuellen Drittanbietermodule findet sich unter [3]. Ein vielversprechendes Framework für die Umsetzung von Webapplikationen ist Alosaur. Es verfolgt eine ähnliche Strategie wie Nest, ein modernes Web Application Framework für Node zu sein. Alosaur ordnet die verschiedenen Bereiche der Applikation in Modulen an. Innerhalb dieser Module stehen einzelne Klassen für die vom Client erreichbaren Endpunkte. Die Methoden der Klassen werden über Decorators ausgezeichnet und damit an die jeweiligen URL-Pfade gebunden. Listing 4 zeigt ein einfaches Beispiel eines Alosaur-Controllers.


@Controller('/todo')
export class TodoController {
  constructor(private service: TodoService) {}
  @Get('/:id')
  json(@Param('id') id: string) {
    return Content(this.service.get(id));
  }
}

Auch hier muss beim Start der Applikation beachten werden, dass der Aufbau einer Netzwerkverbindung erlaubt werden muss, weil die Applikation ansonsten mit einer entsprechenden Fehlermeldung abgebrochen wird.

Deno auf der Kommandozeile

Deno eignet sich nicht nur zur Implementierung von Webservern, sondern deckt durch seine Flexibilität eine große Spanne von Einsatzgebieten ab. Ein typisches Anwendungsgebiet sind Kommandozeilenapplikationen. Gerade im Bereich der Automatisierung von Aufgaben kann Deno punkten. Da Deno-Skripte in JavaScript oder TypeScript verfasst werden, müssen Webentwickler keine zusätzliche Shellskriptsprache erlernen, sondern können die Operationen direkt in JavaScript formulieren. Deno hat mit den passenden Berechtigungen Zugriff auf alle Aspekte des Systems und ist damit eine gute Basis für die verschiedensten Unterstützungsprogramme. Ein wesentlicher Aspekt von Kommandozeilenanwendungen ist die Steuerungsmöglichkeit über Kommandozeilenoptionen. Zu diesem Zweck bietet Deno ein Standardmodul mit dem Namen flags. Dieses Modul basiert auf der populären JavaScript-Bibliothek Minimist, einem Parser für Kommandozeilenoptionen. Deno gibt über die args-Eigenschaft lesenden Zugriff auf die Kommandozeile einer Applikation, wobei der Wert dieser Eigenschaft aus einem Array besteht. Dessen erstes Element ist der Name des Startskripts, also beispielsweise index.ts. Dieser Skriptname ist der Name der Datei, der bei der Ausführung angegeben wurde. Befindet man sich im gleichen Verzeichnis, ist es der direkte Name, in einem übergeordneten Verzeichnis wird der entsprechende Name des Unterverzeichnisses hinzugefügt. Alle weiteren Elemente des args-Arrays sind die Optionen, die beim Aufruf angegeben wurden. Das Problem hierbei ist, dass das Parsen der Optionen in diesem Fall durch den Benutzer manuell ausgeführt werden muss. Es muss also beispielsweise aus einem –file=input. txt etwas gemacht werden, mit dem in der Applikation gearbeitet werden kann. Hinzu kommt, dass es unterschiedliche Arten gibt, wie Optionen angegeben werden: die lange Version –file=input.txt und die Kurzversion -f input.txt. Außerdem gibt es Optionen, die keinen Wert erhalten und lediglich als Boolean Flags wirken. Für diese Unterscheidungen kann auf einen Kommandozeilenparser zurückgegriffen werden. Listing 5 zeigt, wie das flags-Modul von Deno angewendet wird.


const { args } = Deno;
import { parse } from 'https://deno.land/std/flags/mod.ts';
 
const options = parse(args);
 
if (options.version) {
  console.log('Version 1.0.0');
}

Der Quellcode sorgt dafür, dass die Zeichenkette Version 1.0.0 ausgegeben wird, wenn die Option –version beim Aufruf des Skripts übergeben wurde. Damit das funktioniert, übergeben wir die args-Eigenschaft an die parse-Funktion aus dem flags-Modul und erhalten ein Objekt zurück, das für die angegebenen Optionen Eigenschaften aufweist. Bei der version-Option handelt es sich um ein Boolean Flag, sodass es direkt in einem if-Statement verwenden werden kann. Ist die Option nicht gesetzt, existiert die Eigenschaft nicht, der Ausdruck im if-Statement ergibt nicht true und das console.log-Statement wird dementsprechend nicht ausgeführt.

Kompatibilität mit Node

Bei der Entwicklung von Deno wurde bewusst darauf verzichtet, kompatibel zu Node zu sein. Der Grund hierfür ist einfach: Die Kompatibilitätsbestrebungen sollten die Architektur von Deno nicht negativ beeinflussen. Das betrifft vor allem die Implementierung des Modulsystems. Da Deno allerdings mittlerweile im Kern einigermaßen stabil ist, wird nun doch über eine Integration des Node-Ökosystems nachgedacht. Die Entwickler von Deno wissen, dass die Plattform nicht akzeptiert werden würde, wenn sämtliche Node-Bibliotheken für Deno neu implementiert werden müssten. Die Akzeptanz würde sich jedoch erheblich steigern lassen, wenn es einfach wäre, bereits existierende Module in Deno zu verwenden.

An dieser Kompatibilitätsschicht wird aktuell aktiv gearbeitet, es gibt sogar bereits erste vielversprechende Ansätze. Das größte Problem ist hier die Inkompatibilität der Modulsysteme. Das node-Modul von Deno versucht, dieses Problem zu lösen, indem es eine Funktionalität zur Verfügung stellt, mit dem die Importe für das CommonJS-Modulsystem aufgelöst werden. Für das folgende Beispiel muss zunächst die Hilfsbibliothek Lodash mit dem Node Package Manager und dem Kommando npm install lodash installiert werden. Listing 6 zeigt den erforderlichen Quellcode.


import { createRequire } from 'https://deno.land/std/node/module.ts';
 
const require_ = createRequire(import.meta.url);
 
const { intersection } = require_('lodash');
 
const result = intersection([2, 1], [2, 3]);
 
console.log(result);

Zunächst muss die createRequire-Methode des node-Moduls geladen werden, bevor die require-Funktion erzeugt werden kann, die wiederum die Node-Module laden. Der require-Aufruf lädt die Lodash-Bibliothek. Mit einem Destructuring-Statement kann auf die intersection-Funktion zugegriffen werden, mit der die Schnittmenge aus zwei Arrays ermittelt wird. Das Ergebnis wird schließlich auf der Konsole ausgegeben. Für die Ausführung des Skripts muss die allow-read-Option angeben sein, da ansonsten das Laden der Node-Module nicht funktioniert.

Fazit

Der Kerngedanke hinter Deno ist es, die Fehler und Kompromisse, die bei der Entwicklung von Node gemacht wurden, auszubügeln und so eine moderne, stabile und sichere Plattform für serverseitiges JavaScript zu schaffen. So setzt Deno statt auf C++ im Kern auf die Programmiersprache Rust und verfügt über ein zentrales Berechtigungssystem, das den Ausbruch einer Applikation aus einer geschützten Sandbox verhindern soll. Dass Deno noch nicht zu 100 Prozent für den Produktiveinsatz bereit ist, ist schon an der Versionsnummer, aktuell 0.x, und an den Statements der Entwickler, allen voran Ryan Dahl, abzulesen. Deno ist eine Idee und ein Experiment, das durchaus gelingen kann. Die Ideen hinter der Plattform adressieren einige Schwächen von Node und lösen sie auf eine elegante Weise. Außerdem kommen einige Konzepte zum Einsatz, die bei der Entstehung von Node im Jahr 2009 schlicht und ergreifend in JavaScript noch nicht verfügbar waren.

 

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -