如何在Oracle的新Nashorn JS引擎中使用CommonJS模块?

11

我正在寻找适用于Nashorn的模块系统。据我所知,对于JS模块,CommonJS是可行的选择。我已经查阅了列表(这里这里),但在Java方面,很难找到一个完整的CommonJS实现。

Narwhal已不再更新,并且它的文档也不再托管在GitHub上。是否有现成的支持Java的CommonJS实现,或者我应该开始一个新项目呢?

5个回答

18

请查看此处的jvm-npm:https://github.com/nodyn/jvm-npm。该项目被nodyn用作CommonJS模块系统。它“了解”NPM,这意味着您可以直接从NPM加载模块,但它不提供任何Node.js API。

以下是一个简单的使用示例:

$ npm install pegjs
npm http GET https://registry.npmjs.org/pegjs
npm http 200 https://registry.npmjs.org/pegjs
pegjs@0.8.0 node_modules/pegjs
$ jrunscript
nashorn> typeof require
undefined
nashorn> load('./jvm-npm.js')
nashorn> typeof require
function
nashorn> var PEG = require('pegjs');
nashorn> typeof PEG
object

这主要是使用Javascript编写,但从文件系统等加载文件的实际操作是通过Java完成的。


6

我之前在Nashorn邮件列表上问过一个非常类似的问题,以下是Sundar(Nashorn工程师)的回复:

发件人:A. Sundararaj​an

收件人:nashorn-dev@openjdk.java.net

我忘记补充了。Nashorn不包含任何内置模块系统。 但是,如果一个模块系统是纯JS + Java,那么它必须可以在nashorn上运行。

Nashorn支持“load”(从URL、文件、资源加载脚本)和“loadWithNewGlobal”(将脚本加载到全新的全局范围)原语,除了老旧的“eval”之外。因此,任何模块系统都应该可以在纯JS或者也许有一点Java代码的基础上实现在nashorn上。

-Sundar


5

我已经寻找这样的实现有一段时间了。我一直在使用一个稍微修改过的Rhino-Require版本。虽然Rhino声称是CommonJS兼容的,但据我所知,它只实现了模块,而不能解析包(package.json)。 RingoJS应该是兼容的。但Nashorn永远不会看到

后来,Oracle宣布了Avatar项目,它依赖于Avatar.js这里。这是非正式称为Node.jar的官方项目。但目前,您必须自己编译它。该项目非常年轻。

另一个非常年轻的项目是Nodyn,它依赖于dyn.js。

因此,如果理解得好,CommonJs应该与avatar-js和nodyn一起工作,但这两个项目仍然很年轻。我不明白为什么avatar-js没有完全与nashorn一起分发。

一种解决方案是添加一个类似于Rhino的CommonJS兼容性脚本,该脚本添加importClass / importPackage(mozilla_compat.js),它将在nashorn中添加CommonJS兼容性,这是一种经过彻底测试的Rhino-Require shim。


5

我也有相同的需求,曾使用jvm-npm一段时间,但我需要一个即使不允许在JavaScript中使用Java包也能正常工作的工具,因此我在这里编写了自己的版本:https://github.com/coveo/nashorn-commonjs-modules

它完全由Java实现,并支持从文件系统以外的地方加载模块(例如Java资源、自定义数据库等)。

如果有人想使用它,可以在Maven Central上找到。


1

还有nashorn-require,你也可以从github上获取。我用过它,我能够做到

        engine.eval(reader("src/main/javascript/nashorn-require.js"),bindings);
        engine.eval("var initRequire = load('src/main/javascript/nashorn-require.js');",bindings);
        engine.eval("initRequire({mainFile : 'src/main/javascript/foo', debug : true})", bindings);
        engine.eval("var babel = require('babel');",bindings);

然后使用工具将JSX React组件转译为ES5。

        Buffer input = findTemplateSource(fileLocation,context);
        bindings.put("input",input.toString());
        result = engine.eval("babel.transform(input,{ presets: ['react', 'es2015'] }).code;",bindings);

然后,当我将React和React-DOM引入我的浏览器并加载生成的JS组件时,一切都正常工作,所以我确定Babel非常满意,但我不确定它是否能找到第三方插件...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接