Node.js 執行期

GraalVM 可以執行未經修改的 Node.js 應用程式。GraalVM 的 Node.js 執行期基於最新版本的 Node.js,並執行 GraalVM JavaScript 引擎 (GraalJS) 而非 Google V8。某些內部功能 (例如,VM 內部統計資料、組態、效能分析、偵錯等) 不受支援,或支援時行為可能有所不同。

應用程式可以自由匯入和使用 NPM 套件,包括原生套件。

Node.js 入門 #

從適用於 JDK 21 的 GraalVM 開始,GraalVM Node.js 執行期可作為單獨的發行版本提供。Oracle GraalVM 和 GraalVM Community Edition 皆提供兩種獨立的執行期選項:Native Image 編譯的啟動器或基於 JVM 的執行期。為了區分它們,GraalVM Community Edition 版本在名稱中帶有後綴 -communitygraaljs-community-<version>-<os>-<arch>.tar.gzgraalnodejs-community-<version>-<os>-<arch>.tar.gz。隨附 JVM 的獨立版本在名稱中帶有 -jvm 後綴。

若要啟用 GraalVM Node.js 執行期,請安裝基於 Oracle GraalVM 或 GraalVM Community Edition 的 Node.js 發行版本,以適用於您的作業系統。

  1. 導覽至 GitHub 版本 並為您的作業系統選擇所需的獨立版本。

  2. 解壓縮封存
     tar -xzf <archive>.tar.gz
    

    或者,在 Finder 中開啟檔案。

  3. 檢查版本以查看執行期是否處於活動狀態
     ./path/to/bin/node --version
    

執行 Node.js 應用程式 #

Node.js 安裝提供 nodenpm 啟動器

node [options] [filename] [args]

npm 命令等同於預設的 Node.js 命令,並具有額外的 GraalVM 特定功能 (例如,與 Java 的互通性)。可以使用 node --help 取得可用選項的清單。

使用 node 啟動器執行 Node.js 應用程式。例如

  1. 使用 npm install 安裝 colorsansispan 套件,如下所示
     npm install colors ansispan
    

    安裝套件後,您可以從應用程式中使用它們。

  2. 將以下程式碼片段新增至名為 app.js 的檔案,並將其儲存在您安裝 Node.js 套件的相同目錄中
     const http = require("http");
     const span = require("ansispan");
     require("colors");
    
     http.createServer(function (request, response) {
         response.writeHead(200, {"Content-Type": "text/html"});
         response.end(span("Hello Node.js!".green));
     }).listen(8000, function() { console.log("Node.js server running at http://127.0.0.1:8000/".red); });
    
     setTimeout(function() { console.log("DONE!"); process.exit(); }, 2000);
    
  3. 使用 node 命令在 GraalVM Node.js 執行期上執行它,如下所示
     node app.js
    

當從 node 二進位啟動器啟動應用程式時,Node.js 功能可用。從 Java 內容啟動 Node.js 應用程式或存取 NPM 套件時,會有一些限制,請參閱 Node.js 與 Java Script Context

使用 npm 安裝套件 #

若要安裝 Node.js 套件,請使用 npm 啟動器。npm 命令等同於預設的 NPM 命令,並支援其大多數選項。

可以使用以下方式安裝 NPM 套件

npm install [package]

由於 GraalVM Node.js 的 npm 命令與 NPM 大致相容,因此套件會如預期地安裝在 node_modules/ 目錄中。

全域安裝 npm 套件 #

可以使用 npm-g 選項全域安裝 Node 套件。依預設,npm 會將全域套件 (連結到其可執行檔) 安裝在安裝 node 可執行檔的路徑中,通常是 node/bin/。該目錄是安裝全域套件的位置。如果您經常使用全域安裝的套件,尤其是它們的命令列介面,您可能會想要將該目錄新增至您的 $PATH

另一種選項是透過設定 $PREFIX 環境變數,或在執行 npm install 時指定 --prefix 選項,來指定 npm 的全域安裝目錄。例如,以下命令會將全域套件安裝在 /foo/bar/ 目錄中

npm install --prefix /foo/bar -g <package>

有關 prefix 的更多詳細資訊,可以在 官方 NPM 文件中找到。

與 Java 的互通性 #

Node.js 執行期無法嵌入到 JVM 中,但必須作為單獨的處理序啟動。

  1. 將以下程式碼儲存在名為 HelloPolyglot.java 的檔案中並進行編譯
     import org.graalvm.polyglot.*;
     import org.graalvm.polyglot.proxy.*;
    
     public class HelloPolyglot {
    
         static String JS_CODE = "(function myFun(param){console.log('hello '+param);})";
    
         public static void main(String[] args) {
             System.out.println("Hello Java!");
             try (Context context = Context.create()) {
                 Value value = context.eval("js", JS_CODE);
                 value.execute(args[0]);
             }
         }
     }
    
  2. 然後將此程式碼儲存為名為 app.js 的檔案
     var HelloPolyglot = Java.type("HelloPolyglot");
    
     HelloPolyglot.main(["from node.js"]);
    
     console.log("done");
    
  3. 使用 node 執行它
     node --vm.cp=. app.js
    

    您應該會看到以下輸出

     Hello Java!
     hello from node.js
     done
    

然後,Node.js 和 JVM 皆會在相同的處理序中執行,並且互通性會使用與上述相同的 Value 類別運作。

若要了解執行 node 啟動器和從 Java Context 存取 Node.js NPM 模組或 ECMAScript 模組之間的差異,請參閱 NodeJSVSJavaScriptContext

使用 Node.js 的多執行緒 #

GraalJS 的基本多執行緒模型也適用於 Node.js 應用程式。在 Node.js 中,可以建立 Worker 執行緒來並行執行 JavaScript 程式碼,但 JavaScript 物件無法在 Worker 之間共用。相反地,可以使用 GraalVM Java 互通性建立的 Java 物件 (例如,使用 Java.type()) 可以在 Node.js Worker 之間共用。這允許多執行緒 Node.js 應用程式共用 Java 物件。

GraalVM Node.js 單元測試包含多執行緒 Node.js 應用程式的多個範例。最值得注意的範例顯示如何

  1. Node.js 工作執行緒可以執行 Java 程式碼.
  2. Java 物件可以在 Node.js 工作執行緒之間共用.
  3. 可以使用 JavaScript Promise 物件來 await 來自 Worker 的訊息,使用 Java 物件將 Promise 繫結到 Worker 訊息.

常見問題 #

GraalVM 的 Node.js 執行期與原始 Node 實作相容嗎? #

GraalVM 的 Node.js 執行期與原始 Node.js (基於 V8 引擎) 大致相容。這導致大量基於 npm 的模組相容。事實上,在我們測試的 10 萬個 npm 模組中,超過 94% 的模組通過了所有測試。儘管如此,仍必須考慮幾個差異來源

  • 設定: GraalVM 的 Node.js 大部分模擬了 Node 的原始設定,包括 node 可執行檔、npm 和類似的內容。但是,並非所有命令列選項都受支援 (或行為完全相同)。模組可能需要針對 v8.h 檔案 (重新) 編譯原生模組。

    從適用於 JDK 21 的 GraalVM 開始,GraalVM Node.js 執行期可作為單獨的發行版本提供。請參閱Node.js 入門

  • 內部: GraalVM 的 Node.js 是在 JVM 之上實作的,因此具有與基於 V8 的 Node.js 不同的內部架構。這表示某些內部機制的行為有所不同,並且無法完全複製 V8 行為。這幾乎不會影響使用者程式碼,但可能會影響以原生方式實作的模組,這取決於 V8 內部機制。

  • 效能: 由於 GraalVM 的 Node.js 是在 JVM 之上實作的,因此效能特性與原始原生實作有所不同。雖然 GraalVM 的尖峰效能在許多基準測試中可以與 V8 相匹配,但通常需要更長的時間才能達到尖峰 (稱為預熱)。在測量 (尖峰) 效能時,請務必給 Graal 編譯器一些額外的時間。

  • 相容性: GraalVM 的 Node.js 執行期使用以下方法來檢查並保留與 Node.js 程式碼的相容性

    • node-compat-table:GraalVM 的 Node.js 使用 node-compat-table 模組與其他引擎進行比較,突顯可能中斷 Node.js 程式碼的不相容性。
    • 使用 mocha 自動進行大量模組測試:為了測試大量模組,GraalVM 的 Node.js 執行期會針對使用 mocha 測試框架的 9.5 萬個模組進行測試。使用 mocha 可以自動化執行測試並理解測試結果的過程。
    • 人工測試熱門模組:在人工測試設定中測試了精選的 npm 模組清單。這些高度相關的模組會以更複雜的方式進行測試。

NPM 套件可以全域安裝嗎? #

可以使用 npm-g 選項全域安裝 Node 套件,GraalVM 的 Node.js 實作也是如此。

雖然原始 Node.js 實作有一個主要目錄 (node/bin/) 來放置二進位檔案和全域安裝的套件及其命令列工具,但 GraalVM 的 Node.js 會將二進位檔案放在 /path/to/graaljs/bin/ 目錄中。在 GraalVM Node.js 執行期上全域安裝 NPM 套件時,可執行檔的連結 (例如,命令列介面工具的連結) 會放置到 JavaScript 特定目錄中。為了使全域安裝的套件正常運作,您可能需要將 /path/to/graaljs/bin 新增至您的 $PATH

另一個選項是透過設定 $PREFIX 環境變數,或在執行 npm install 時指定 --prefix 選項,來指定 npm 的全域安裝目錄。

如需更多詳細資訊,請參閱全域安裝 npm 套件

與我們聯繫