NGINX JavaScriptモジュール(njs)を2015年に当初の名称であるnginScriptとして導入し、2017年<.htmla>に一般提供を開始して以来、数十回にわたるバージョンアップデートを通じて、新機能の追加と実装の改良を着実に続けてきました。通常、新しいNGINX JavaScriptバージョンの機能についてはNGINX Plusのリリースに合わせてご紹介していますが、バージョン0.7.7は非常に魅力的なため、今回は待ちきれません!
njs 0.7.7の大幅な機能強化により、NGINXの設定をさらにモジュール化し、整理された再利用可能なものにできます。
- njsコードをグローバルに宣言するのではなく、適用されるコンテキストで宣言できるようになり、カスタムコードを使用箇所の近くに配置できます。
- njsコード自体のフックにより、実行コンテキストに応じて動作を変更できます。
- 新しい「
fs.FileHandle」オブジェクトにより、ファイル操作が効率化されます。
njsの詳細と、サンプルコードを提供しているユースケースの一覧については、F5のブログ記事「NGINX JavaScriptモジュールでリクエストごとにJavaScriptのパワーと利便性を活用」をご覧ください。
njs 0.7.7のすべての新機能とバグ修正の一覧については、「変更点」ドキュメントをご覧ください。
ローカルコンテキストでのJavaScriptコードと変数の宣言
以前のバージョンのnjsでは、JavaScriptコードをインポートし、関連する変数をjs_import、js_path、js_set、js_varの各ディレクティブを使用して、最上位のhttpまたはstreamコンテキストで宣言する必要があります。これは、メインファイルの先頭でグローバル変数を宣言することに相当します。しかし、JavaScriptの関数や変数を実際に呼び出すディレクティブは子コンテキストに記述します。たとえば、HTTPのjs_contentディレクティブはlocation{}ブロックに、Streamのjs_accessディレクティブはserver{}ブロックに記述します。このため、次の2つの問題が生じます。
- 設定を読む人にとって、
httpおよびstreamコンテキスト内の宣言は、関連するコードや変数が実際にどこで使用されているかが示されていないため、実質的にノイズとなります。 - 子コンテキストでは、コードと変数がどこからインポートされ、どこで宣言されているのかが明確ではありません。推奨される構成は、
http{}ブロックとstream{}ブロックをメインの設定ファイル(nginx.conf)にのみ記述し、includeディレクティブを使用して、/etc/nginx/conf.dディレクトリと/etc/nginx/stream.dディレクトリから、機能別に分割した小規模な設定ファイルを読み込む方法です。ただし、NGINXの設定には柔軟性があり、http{}ブロックとstream{}ブロックを複数のファイルに記述することもできます。複数の担当者がNGINXの設定を扱い、必ずしも既定の規則に従うとは限らない環境では、特に問題となる可能性があります。
njs 0.7.7以降では、コードを使用するコンテキストでコードをインポートし、変数を宣言できます。
- HTTP –
- Stream –これらのディレクティブは、
serverコンテキストだけでなく、streamコンテキストにも記述できます:
特定のユースケースに必要なnjs設定をすべて1つのファイルにまとめることで、コードのモジュール性と移植性も向上します。
たとえば、以前のバージョンのnjsでは、新しいスクリプトを追加する際に、nginx.conf(js_importに加え、必要に応じてjs_path、js_set、js_varを追加)と、JavaScript関数を呼び出すファイル(ここではjscode_local.conf)の両方を変更する必要がありました。
コード例を読み込み中…
コード例を読み込み中…
njs 0.7.7以降では、util関数に関連するすべての設定が1つのファイル「jscode_integrated.conf」にまとめられています:
コード例を読み込み中…
実行コンテキストに応じた動作の変更
njs 0.7.7のいくつかの新機能により、JavaScriptコードが実行されるコンテキスト(処理フェーズ)に応じて、その動作を変更できます。
HTTPの「r.internal」プロパティ
HTTPの「r.internal」プロパティは、内部リクエスト(「location{}」ブロックに「internal」ディレクティブが含まれる場合に処理されるリクエスト)に対して「true」に設定されるブールフラグです。スクリプトで内部コンテキストと非内部コンテキストの両方から呼び出せる汎用イベントハンドラーを使用する場合、「r.internal」フラグを使用してロジックを分岐できます。
以下は内部リクエストに分類されます。
- 次のディレクティブによってリダイレクトされたリクエスト:
error_page、index、random_index、およびtry_filesdirectives - アップストリームサーバーからの「
X-Accel-Redirect」レスポンスヘッダーによってリダイレクトされたリクエスト - 次の要素によって呼び出されるサブリクエスト:
auth_requestおよびmirrorディレクティブ、ngx_http_addition_moduleモジュールのディレクティブ、またはServer Side Include(SSI)のincludevirtualコマンド(ngx_http_ssi_moduleモジュールでサポート) - Requests changed by the
rewriteディレクティブによって変更されたリクエスト
改善された「s.send()」ストリームメソッド
以前のバージョンのnjsでは、Streamのs.send()メソッドはコンテキストに依存していました。データの送信方向は、このメソッドを呼び出すコールバックの位置(アップストリームまたはダウンストリーム)によって決まるためです。この仕組みは、s.send()が当初対象としていた同期コールバックでは問題なく機能しますが、ngx.fetch()などの非同期関数では機能しません。
njs 0.7.7以降では、方向が別の内部フラグに保存されるため、s.send()でそのフラグを使用できます。
新しいfs.FileHandle()オブジェクトによるファイル操作の効率化
ファイルシステムモジュール(fs)は、ファイルに対する操作を実装します。FileHandleは、fsモジュールに新たに追加された、数値ファイル記述子をラップするオブジェクトです。FileHandleオブジェクトのインスタンスは、fs.promises.open()メソッドによって作成されます。
Use the FileHandleオブジェクトを使用してファイル記述子を取得すると、さらに次の操作に使用できます。
- ファイルに対して
read()やwrite()などの関数を実行する - ファイル全体を読み込まずにファイルを開き、指定した位置で読み取りと書き込みを行う
以下のFileHandleプロパティが実装されています(各プロパティの必須引数とオプション引数については、ドキュメントを参照してください):
filehandle.fdfilehandle.read()filehandle.stat()filehandle.write()filehandle.write()filehandle.close()
以下のメソッドは、FileHandleをサポートするように更新されました(各メソッドの引数については、リンク先のドキュメントを参照してください)。
njsを使用して構成を強化
njs 0.7.7では、チームによるnjsコードの開発と共有が容易になりました。njsディレクティブを使用できるコンテキストが拡張され、カスタムJavaScriptコードによるNGINX設定の強化がさらに簡単になりました。単なるミドルウェアやエッジコンポーネントにとどまらないAPIゲートウェイ、リバースプロキシ、Webサーバーの構築に向けた第一歩を踏み出せます。スタックに別のコンポーネントを追加することなく、JavaScript、TypeScript、またはサードパーティ製のnodeモジュールを通じて、NGINXをアプリケーションの一部として組み込めます。必要なのはNGINXだけです!
ご不明な点がある場合は、NGINX Community Slackに参加し、#njs-code-reviewチャンネルをご覧ください。詳しい情報を確認したり、質問したり、njsコードへのフィードバックを受けたりできます。
関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります