Seit der Einführung des NGINX JavaScript-Moduls (njs) im Jahr 2015 (damals noch unter dem Namen nginScript) und seiner allgemeinen Verfügbarkeit im Jahr 2017<.htmla> haben wir über Dutzende von Versionsupdates hinweg kontinuierlich neue Funktionen hinzugefügt und unsere Implementierung optimiert. Normalerweise warten wir auf ein NGINX Plus-Release, um die Funktionen einer neuen NGINX JavaScript-Version vorzustellen. Doch Version 0.7.7 begeistert uns so sehr, dass wir diesmal einfach nicht warten können!
Die bedeutenden Verbesserungen in njs 0.7.7 tragen dazu bei, Ihre NGINX-Konfiguration noch modularer, übersichtlicher und wiederverwendbarer zu gestalten:
- Sie können njs-Code jetzt in den Kontexten deklarieren, in denen er verwendet wird, anstatt ihn global zu deklarieren. So befindet sich Ihr benutzerdefinierter Code näher am Ort seiner Verwendung.
- Hooks im njs-Code selbst ermöglichen es Ihnen, das Verhalten abhängig vom Ausführungskontext anzupassen.
- Das neue
fs.FileHandle-Objekt macht Dateioperationen effizienter.
Weitere Informationen zu njs und eine Übersicht der Anwendungsfälle, für die wir Beispielcode bereitstellen, finden Sie im Beitrag „Die Leistungsfähigkeit und Benutzerfreundlichkeit von JavaScript für jede Anfrage mit dem NGINX JavaScript-Modul nutzen“ in unserem Blog.
Eine vollständige Liste aller neuen Funktionen und Fehlerbehebungen in njs 0.7.7 finden Sie in der Änderungsübersicht.
JavaScript-Code und Variablen in lokalen Kontexten deklarieren
In früheren njs-Versionen müssen Sie Ihren JavaScript-Code importieren und die relevanten Variablen – mit den Direktiven js_import, js_path, js_set und js_var – im übergeordneten http- oder stream-Kontext deklarieren. Dies entspricht der Deklaration globaler Variablen am Anfang einer Hauptdatei. Die Direktiven, die die JavaScript-Funktionen und -Variablen tatsächlich aufrufen, befinden sich jedoch in einem untergeordneten Kontext – beispielsweise die Direktive js_content in einem HTTP-location{}-Block und die Direktive js_access in einem Stream-server{}-Block. Dadurch entstehen zwei Probleme:
- Für jemanden, der die Konfiguration durchliest, sind die Deklarationen in den Kontexten
httpundstreamim Grunde nur störend, da nicht ersichtlich ist, wo der zugehörige Code und die Variablen tatsächlich verwendet werden. - Im untergeordneten Kontext ist nicht ersichtlich, wo der Code und die Variablen importiert und deklariert wurden. Wir empfehlen zwar, die Blöcke
http{}undstream{}nur in die Hauptkonfigurationsdatei (nginx.conf) aufzunehmen und mit der Direktiveincludekleinere, funktionsspezifische Konfigurationsdateien aus den Verzeichnissen /etc/nginx/conf.d und /etc/nginx/stream.d einzulesen, doch die NGINX-Konfiguration ist flexibel – Sie können die Blöckehttp{}undstream{}in mehrere Dateien aufnehmen. Dies kann insbesondere in Umgebungen problematisch sein, in denen mehrere Personen an Ihrer NGINX-Konfiguration arbeiten und sich möglicherweise nicht immer an die festgelegten Konventionen halten.
Ab njs 0.7.7 können Sie Code importieren und Variablen in den Kontexten deklarieren, in denen sie verwendet werden:
- HTTP –
- Stream – Diese Direktiven können sowohl im
server-Kontext als auch imstream-Kontext vorkommen:
Wenn Sie die gesamte njs-Konfiguration für einen bestimmten Anwendungsfall in einer einzigen Datei zusammenfassen, wird Ihr Code außerdem modularer und portabler.
Wenn Sie beispielsweise in früheren njs-Versionen ein neues Skript hinzugefügt haben, mussten Sie sowohl die Datei nginx.conf ändern (indem Sie js_import und gegebenenfalls js_path, js_set und js_var hinzufügten) als auch die Datei, in der die JavaScript-Funktion aufgerufen wird (hier: jscode_local.conf).
Codebeispiel wird geladen…
Codebeispiel wird geladen…
Ab njs 0.7.7 befindet sich die gesamte Konfiguration für die util-Funktion in einer einzigen Datei, jscode_integrated.conf:
Codebeispiel wird geladen…
Verhalten abhängig vom Ausführungskontext ändern
Mehrere neue Funktionen in njs 0.7.7 ermöglichen es Ihnen, das Verhalten Ihres JavaScript-Codes abhängig vom Kontext (der Verarbeitungsphase), in dem er ausgeführt wird, anzupassen.
Die HTTP-r.internal-Eigenschaft
Die HTTP-Eigenschaft „r.internal“ ist ein boolesches Flag, das bei internen Anfragen auf „true“ gesetzt wird (diese werden von location{}-Blöcken verarbeitet, die die Direktive „internal“ enthalten). Mit dem Flag „r.internal“ können Sie die Programmlogik verzweigen, wenn ein Skript einen allgemeinen Ereignishandler verwendet, der sowohl in internen als auch in nicht internen Kontexten aufgerufen werden kann.
Folgende Anfragen werden als interne Anfragen eingestuft:
- Anfragen, die durch die Direktiven „
error_page“, „index“, „random_index“ und „try_files“ umgeleitet werden - Anfragen, die durch den
X-Accel-Redirect-Antwortheader eines Upstream-Servers umgeleitet werden - Unteranfragen, die durch die Direktiven „
auth_request“ und „mirror“, die Direktiven im Modul „ngx_http_addition_module“ oder den Server-Side-Include-Befehl (SSI) „includevirtual“ aufgerufen werden (unterstützt durch das Modul „ngx_http_ssi_module“) - Durch die
rewrite-Direktive geänderte Anfragen
Verbesserte s.send()-Stream-Methode
In früheren njs-Versionen ist die Stream-Methode „s.send()“ kontextabhängig, da die Richtung, in die sie Daten sendet, von der Position (Upstream oder Downstream) des Callbacks bestimmt wird, in dem die Methode aufgerufen wird. Dies funktioniert gut bei synchronen Callbacks – für die s.send() ursprünglich konzipiert wurde –, schlägt jedoch bei asynchronen Funktionen wie ngx.fetch() fehl.
In njs 0.7.7 und höher wird die Richtung in einem separaten internen Flag gespeichert, das s.send() anschließend verwenden kann.
Effizientere Dateioperationen mit dem neuen fs.FileHandle()-Objekt
Das Dateisystemmodul (fs) stellt Funktionen für Dateioperationen bereit. Das neue FileHandle-Objekt im fs-Modul dient als Objekt-Wrapper für einen numerischen Dateideskriptor. Instanzen des FileHandle-Objekts werden mit der Methode fs.promises.open() erstellt.
Verwenden Sie das FileHandle-Objekt, um einen Dateideskriptor abzurufen, der anschließend für Folgendes verwendet werden kann:
- Funktionen wie
read()undwrite()für die Datei ausführen - Eine Datei öffnen und an einer bestimmten Stelle Lese- und Schreibvorgänge durchführen, ohne die gesamte Datei einzulesen
Die folgenden Eigenschaften von FileHandle wurden implementiert (Informationen zu den erforderlichen und optionalen Argumenten der einzelnen Eigenschaften finden Sie in der Dokumentation):
filehandle.fdfilehandle.read()filehandle.stat()filehandle.write()filehandle.write()filehandle.close()
Diese Methoden wurden aktualisiert und unterstützen nun FileHandle (Informationen zu den Argumenten der einzelnen Methoden finden Sie in der verlinkten Dokumentation):
fs.openSync()fs.promises.open()fs.fstatSync()fs.readSync()fs.writeSync()(Puffer)fs.writeSync()(Zeichenfolge)
Verwenden Sie njs, um Ihre Konfiguration zu optimieren
Mit njs 0.7.7 haben wir es Ihren Teams erleichtert, gemeinsam an njs-Code zu arbeiten und ihn zu teilen. Dank der erweiterten Kontexte für njs-Direktiven lässt sich die NGINX-Konfiguration noch einfacher mit benutzerdefiniertem JavaScript-Code erweitern. So können Sie den ersten Schritt hin zu einem API-Gateway, Reverse-Proxy oder Webserver machen – und zwar zu einem, der mehr ist als nur eine weitere Middleware- oder Edge-Komponente. Über JavaScript, TypeScript oder Node-Module von Drittanbietern können Sie ihn in Ihre Anwendung integrieren, ohne Ihrem Stack eine weitere Komponente hinzuzufügen. Alles, was Sie brauchen, ist NGINX!
Haben Sie Fragen? Treten Sie dem NGINX Community Slack bei und besuchen Sie den Kanal #njs-code-review, um mehr zu erfahren, Fragen zu stellen und Feedback zu Ihrem njs-Code zu erhalten.
Über den Autor
Ähnliche Blogbeiträge
Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln
Beim NGINX Sprint 2022 besinnen wir uns auf unsere Open-Source-Wurzeln. Erfahren Sie mehr über die Initiativen, die wir im kommenden Jahr verfolgen, und teilen Sie uns mit, was Sie sich wünschen.

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
Ein Ingress-Controller kann eines der leistungsstärksten Tools in Ihrem Kubernetes-Stack sein. Erfahren Sie, wie Sie Ihre Ingress-Anforderungen ermitteln, um die beste Option auszuwählen.
Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet
Wir haben kürzlich den Lösungsleitfaden zum NGINX Ingress Controller um Empfehlungen zur Dimensionierung für Amazon Elastic Kubernetes Service (EKS) ergänzt. In diesem Blogbeitrag erläutern wir, wie wir diese Empfehlungen erarbeitet haben, und stellen Ihnen alle Informationen zur Verfügung, die Sie benötigen, um selbst ähnliche Tests durchzuführen.

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77
Bei der Fehlersuche bei Datenverkehrsproblemen zwischen NGINX und Upstream-Servern konnte CDN77 die benötigten Daten nur aus dem Fehlerprotokoll mit aktivierter Debug-Ausgabe beziehen, was die Leistung beeinträchtigt und riesige Dateien erzeugt. Daher entwickelte das Team ein neues benutzerdefiniertes Modul, das ausschließlich die benötigten Daten protokolliert.
Ankündigung von NGINX Plus R16
NGINX Plus R16 ist eine einheitliche, elastische Ingress- und Egress-Schicht für Anwendungen, die die Funktionen eines Load Balancers, API-Gateways und einer WAF vereint und neue Features wie clusterfähige Ratenbegrenzung, Schlüssel-Wert-Speicher, „Random with Two Choices“, verbessertes UDP-Load-Balancing und vieles mehr bietet.
5 Gründe für den Umstieg auf softwarebasiertes Load Balancing
Entdecken Sie fünf Gründe für den Wechsel zu einem softwarebasierten Load Balancer wie NGINX Plus, darunter Kosteneinsparungen, die Einführung von DevOps und eine einheitliche Lösung für alle Umgebungen.