- 适用于 JDK 24 的 GraalVM(最新)
- 适用于 JDK 25 的 GraalVM(早期访问)
- 适用于 JDK 21 的 GraalVM
- 适用于 JDK 17 的 GraalVM
- 存档
- 开发构建
Node.js 运行时
GraalVM可以运行未经修改的Node.js应用程序。GraalVM的Node.js运行时基于最新版本的Node.js,并运行GraalVM JavaScript引擎(GraalJS)而非Google V8。某些内部功能(例如,VM内部统计、配置、性能分析、调试等)不受支持,或支持但行为可能有所不同。
应用程序可以自由导入和使用NPM包,包括原生包。
Node.js入门 #
从GraalVM for JDK 21开始,GraalVM Node.js运行时作为单独的发行版提供。Oracle GraalVM和GraalVM社区版都提供两种独立的运行时选项:Native Image编译的启动器或基于JVM的运行时。为了区分它们,GraalVM社区版在名称中带有后缀-community
:graaljs-community-<version>-<os>-<arch>.tar.gz
,graalnodejs-community-<version>-<os>-<arch>.tar.gz
。带有JVM的独立版本在名称中带有-jvm
后缀。
要启用GraalVM Node.js运行时,请为您的操作系统安装基于Oracle GraalVM或GraalVM社区版的Node.js发行版。
-
导航到GitHub发布页面并为您的操作系统选择所需的独立版本。
- 解压归档文件
tar -xzf <archive>.tar.gz
或者,在Finder中打开文件。
- 检查版本以查看运行时是否激活
./path/to/bin/node --version
运行Node.js应用程序 #
Node.js安装提供了node
和npm
启动器
node [options] [filename] [args]
npm
命令等同于默认的Node.js命令,并具有额外的GraalVM特定功能(例如,与Java的互操作性)。可用选项列表可以通过node --help
获取。
使用node
启动器执行Node.js应用程序。例如
- 如下使用
npm install
安装colors
和ansispan
包npm install colors ansispan
包安装完成后,您可以在应用程序中使用它们。
- 将以下代码片段添加到名为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);
- 如下使用
node
命令在GraalVM Node.js运行时上执行它node app.js
当应用程序从node
二进制启动器启动时,Node.js功能可用。从Java上下文启动Node.js应用程序或访问NPM包时会受到某些限制,请参阅Node.js与JavaScript上下文。
使用npm
安装包 #
要安装Node.js包,请使用npm
启动器。npm
命令等同于默认的NPM命令,并支持其大部分选项。
可以使用以下命令安装NPM包
npm install [package]
由于GraalVM Node.js的npm
命令与NPM大部分兼容,因此包会像预期一样安装在node_modules/目录中。
全局安装npm
包 #
Node包可以使用npm
和-g
选项全局安装。默认情况下,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中,而必须作为独立进程启动。
- 将以下代码保存到名为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]); } } }
- 然后将此代码保存到名为app.js的文件中
var HelloPolyglot = Java.type("HelloPolyglot"); HelloPolyglot.main(["from node.js"]); console.log("done");
- 使用
node
运行它node --vm.cp=. app.js
您应该看到以下输出
Hello Java! hello from node.js done
Node.js和JVM随后在同一个进程中运行,并且互操作性使用与上述相同的Value
类。
有关运行node
启动器与从Java Context
访问Node.js NPM模块或ECMAScript模块之间的差异,请参阅Node.js与JavaScript上下文。
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应用程序示例。最值得注意的示例展示了如何
- Node.js worker线程可以执行Java代码.
- Java对象可以在Node.js worker线程之间共享.
- 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文件(重新)编译。从GraalVM for JDK 21开始,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包可以全局安装吗? #
Node包可以使用npm
和-g
选项全局安装,这在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
包。