java中呼叫npm模組

rockswang發表於2019-02-16

一些小的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()

相關文章