一些小的javascript片段可以很方便的直接使用ScriptEngine.eval()直接匯入,但是如何使用require方法匯入使用npm下載的javascript模組呢?
答案是使用jvm-npm這個專案。
- 首先,建立一個目錄放置所有javascript檔案,比如:
D:\path\to\js_modules\
- 從jvm-npm下載jvm-npm.js,放到上述目錄中
- 使用
npm i <js_module> -g
下載你需要引用的npm模組,注意看最後的提示,即模組下載目錄 - 到模組下載目錄,通常為<User_Dir>
pm
ode_modules<js_module>,裡面一般有個dist目錄,從裡面找到完整的模組js檔案,複製到上述目錄 - 見以下Kotlin示例程式碼:(注意把js_module換成你需要載入的模組名)
val JS_ROOT = "D:\path\to\js_modules"
val JSE = ScriptEngineManager().getEngineByName("nashorn").apply {
System.setProperty("user.dir", JS_ROOT) // 設定jvm-npm的當前目錄
eval(Util.readLocalUtfText("$JS_ROOT\jvm-npm.js")) // 在ScriptEngine中載入jvm-npm.js
println(eval("typeof require")) // 驗證require方法已正確引入
eval("var mylib = require(`js_module`)") // 這時候,就可以用require()方法來引入當前目錄中的js模組了
println(eval("typeof mylib")) // 驗證js模組已正確載入
}
...
val bar = JSE.eval("mylib.foo()") // js程式碼中可以使用載入的js模組了
注意:
- jvm-npm有個bug,如果你的js檔案大於64K,則會導致檔案截斷。
這種情況下你需要編寫一個能一次讀取完整File或InputStream的java方法,替換掉下面這句:
return new Scanner(input).useDelimiter(`\A`).next()