溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么進行Node.js擴展開發(fā)

發(fā)布時間:2022-08-30 09:42:48 來源:億速云 閱讀:149 作者:iii 欄目:web開發(fā)

這篇文章主要講解了“怎么進行Node.js擴展開發(fā)”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么進行Node.js擴展開發(fā)”吧!

怎么進行Node.js擴展開發(fā)

為什么要開發(fā)Node.js擴展

1.Node.js不適合cpu密集型業(yè)務,開發(fā)擴展使用libuv線程池做異步計算

2.需要更高的執(zhí)行性能,例如使用c++、Rust等比javascript更高效的語言

3.已有c++庫,直接封裝成Node.js擴展提供給javascript調用,避免重復開發(fā)

4.通過javascript無法實現(xiàn)的能力,開發(fā)擴展增強Node.js能力

什么是Node.js擴展

Node.js擴展是文件擴展名為.node的二進制文件,本質上是動態(tài)鏈接庫,可以理解為改了名的.dll或.so文件,可以被require加載

Node.js module官方文檔 nodejs.cn/api/modules…

怎么進行Node.js擴展開發(fā)

Node.js擴展的三種形式

擴展類型基本描述Node.js版本變化時改代碼Node.js版本變化時重新編譯
直接寫C++直接引用v8、libuv等庫進行開發(fā)
NAN使用NAN(Native Abstraction for Node.js)進行開發(fā)
N-API使用node-addon-api進行開發(fā)否(ABI版本需一致)否(ABI版本需一致)
直接寫C++代碼開發(fā)插件,當Node.js版本變化時引用的v8、libuv等庫的版本可能發(fā)生變化,這些三方庫的api也可能會變化,導致需要修改代碼

NAN方式開發(fā)插件,引用nan.h需要在Node.js版本變化時重新編譯

N-API方式調用Node.js穩(wěn)定的二進制ABI接口(Application Binary Interface),只要ABI版本號一致就不需要重新編譯復制代碼

我們可以從Node.js官網(wǎng)歷史版本下載頁面,NODE_MODULE_VERSION看到Node.js版本與ABI版本的對應關系,nodejs.org/zh-cn/downl…

怎么進行Node.js擴展開發(fā)

或者執(zhí)行process.versions.modules查看ABI版本;process.versions查看相關配套版本:

> process.versions
{
  node: '18.0.0',
  v8: '10.1.124.8-node.13',
  uv: '1.43.0',
  zlib: '1.2.11',
  brotli: '1.0.9',
  ares: '1.18.1',
  modules: '108',
  nghttp2: '1.47.0',
  napi: '8',
  llhttp: '6.0.4',
  openssl: '3.0.2+quic',
  cldr: '41.0',
  icu: '71.1',
  tz: '2022a',
  unicode: '14.0',
  ngtcp2: '0.1.0-DEV',
  nghttp3: '0.1.0-DEV'
}

我們來看下官方的Node.js擴展代碼示例:github.com/nodejs/node… 對于N-API方式來說,c語言對應示例代碼中的napi案例,c++對應示例代碼中的node-addon-api案例,引用的頭文件不同。

怎么進行Node.js擴展開發(fā)

怎么進行Node.js擴展開發(fā)

安裝依賴項

首先,需要安裝依賴,按官方的說法可以使用windows-build-tools安裝所有依賴。 nodejs.cn/api/n-api.h…

怎么進行Node.js擴展開發(fā)

但是,公司內網(wǎng)環(huán)境一直安裝失敗,按照文檔嘗試改了各種參數(shù)還是失敗,可能是公司內網(wǎng)環(huán)境問題。如果你也遇到類似問題,可以嘗試手動安裝依賴。 github.com/felixrieseb…

手動安裝步驟如下:

1.安裝node-gyp

npm install -g node-gyp

2.安裝Visual Studio Build Tools

怎么進行Node.js擴展開發(fā)

安裝完成后更新npm配置,例如我安裝的版本號是2022

怎么進行Node.js擴展開發(fā)

npm config set msvs_version 2022

安裝headers,頭文件和Node.js版本是對應的,如果用nvm等工具切換過Node.js版本,請重新安裝

node-gyp install --dist-url=http://mirrors.tools.huawei.com/Node.js/

此步驟會將node_api.h等頭文件下載到本地,按Node.js版本號區(qū)分目錄,例如:

C:\Users\z00443016\AppData\Local\node-gyp\Cache\18.0.0\include\node

配置IDE時會需要用到,當前可以忽略,后續(xù)的文章會再介紹具體配置

3.安裝python

安裝完成后將python和python/Scripts/目錄加入到Path環(huán)境變量

怎么進行Node.js擴展開發(fā)

更新npm配置,

npm config set python D:\runtime\python復制代碼

從hellow world開始

以c++開發(fā)為例,復制官網(wǎng)示例到本地。github.com/nodejs/node…

怎么進行Node.js擴展開發(fā)

執(zhí)行npm install會自動調用node-gyp編譯,生成build/Release/hello.node的目標文件,這個文件就是最終被js引用的擴展包,可以被require調用。

怎么進行Node.js擴展開發(fā)

執(zhí)行示例文件中的hello.js,會調用hello.cc中定義的hello方法輸出'world'。

var addon = require('bindings')('hello');

// 或者直接require hello.node文件
// var addon = require('./build/Release/hello.node');

console.log(addon.hello()); // 'world'

如需重新編譯,可以執(zhí)行node-gyp rebuild,或者執(zhí)行node-gyp help了解其他命令

至此,一個Node.js擴展demo就完成了。

拋出問題

Node.js使用非阻塞io的方式,在一個線程內可以異步處理多個任務,但是如果有一個cpu密集型的任務一直在處理,那么就會阻塞其他任務,響應時間變長。

Node.js官網(wǎng)的解釋如下 nodejs.cn/learn/the-n…

怎么進行Node.js擴展開發(fā)

開發(fā)Node.js擴展是解決問題的方式之一,最終使用什么方式去解決問題,需要基于我們對Node.js的理解,找到最佳實踐。在上述場景中,我們可以使用libuv提供的線程池來異步處理這些cpu消耗較高的任務,從而不會阻塞其他任務的執(zhí)行。

怎么進行Node.js擴展開發(fā)

當然了,web server并不適合處理cpu密集型任務,如果這個cpu密集型的任務調用頻繁且耗時較高,就需要考慮從業(yè)務維度拆分,將任務挪到消息隊列消費端執(zhí)行。

環(huán)境配置

vsCode安裝c++ intelliSense擴展應用

怎么進行Node.js擴展開發(fā)

配置.vscode/c_cpp_properties.json,主要在includePath中配置好headers路徑

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**",
                "C:\Users\${userName}\AppData\Local\node-gyp\Cache\18.0.0\include\node",
                "D:\tool\nvm\v18.0.0\node_global\node_modules\node-addon-api"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "cStandard": "c17",
            "cppStandard": "c++17",
            "intelliSenseMode": "windows-msvc-x64"
        }
    ],
    "version": 4
}

配置.vscode/launch.json,完成調試配置就可以斷點調試了。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "c++ launch",
            "type": "lldb",
            "request": "launch",
            "program": "D:\runtime\nodejs\node.exe",
            "args": ["${workspaceFolder}/src/hello.js"],
            "stopAtEntry": true,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "lldb",
            "setupCommands": [
                {
                    "description": "為 gdb 啟用整齊打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

asyncWork擴展開發(fā)

可以參考官網(wǎng)示例,在項目中的Execute方法中添加自定義代碼,不妨動手一式。github.com/nodejs/node…

node-gyp構建工具

node-gyp是Node.js擴展的構建工具,依賴python和Visual Studio Build Tools,基于google的gyp(Generate Your Projects)工具,chromium、v8等項目也在使用gyp構建。還可以使用CMake.js等工具進行編譯構建。

npm config set msvs_version 2022
npm config set python D:\runtime\python

在package.json中定義"gypfile": true,執(zhí)行npm install時會自動調用ndoe-gyp執(zhí)行build操作。github.com/nodejs/node…

{
  "name": "hello_world",
  "version": "0.0.0",
  "description": "Node.js Addons Example #1",
  "main": "hello.js",
  "private": true,
  "dependencies": {
    "bindings": "~1.2.1",
    "node-addon-api": "^1.0.0"
  },
  "scripts": {
    "test": "node hello.js"
  },
  "gypfile": true
}

node-pre-gyp預構建

由于編譯是基于操作系統(tǒng)和硬件平臺進行的,node-gyp構建生成的.node動態(tài)鏈接庫不能跨平臺,所以通常我們在使用Node.js擴展時以依賴包的形式引入項目,當執(zhí)行npm install時,自動調用node-gyp生成當前環(huán)境可用的.node擴展包。

上述方式需要即時編譯,無疑會拖慢npm install過程。于是就出現(xiàn)了node-pre-gyp預構建工具,直接從倉庫下載當前環(huán)境可用的Node.js擴展包。

以Xprofiler為例,根據(jù)當前系統(tǒng)、硬件平臺、Node.js的ABI版本生成下載地址,定義在package.json的binary字段:

"binary": {
    "module_name": "xprofiler",
    "module_path": "./build/binding/{configuration}/{node_abi}-{platform}-{arch}/",
    "remote_path": "./v{version}/",
    "package_name": "{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz",
    "host": "https://github.com/X-Profiler/xprofiler/releases/download"
},

mirrors.tools.huawei.com/xprofiler/v…

怎么進行Node.js擴展開發(fā)

其他形式的擴展 napi-rs

rust語言非?;鸨贜ode.js開發(fā)領域也大有成為基礎設施的趨勢。比如,Node.js作者的新項目Deno就是用rust語言開發(fā)的;使用swc開發(fā)的編譯工具替代Babel提升性能;rust支持編譯成Webassembly,在前后臺都能執(zhí)行,具有很好的前景。

很多公司對rust語言十分重視,例如下圖中的TOP公司已經(jīng)成為rust基金會白金會員,用實際行動支持rust語言的發(fā)展。foundation.rust-lang.org/

怎么進行Node.js擴展開發(fā)

類似c++項目使用napi開發(fā)Node.js擴展,社區(qū)出現(xiàn)了napi-rs項目來支持rust語言開發(fā)Node.js擴展。github.com/napi-rs/nap…

直接調用動態(tài)鏈接庫 node-ffi

FFI(Foreign Function Interface)語言交互接口,用一種編程語言寫的程序能調用另一種編程語言寫的函數(shù),基本上成熟的編程語言都支持。使得我們可以在Node.js中直接調用c/c++、go、rust等語言編譯生成的動態(tài)鏈接庫,示例如下: github.com/node-ffi/no…

例如libmylibrary.dll或libmylibrary.so動態(tài)鏈接庫的代碼,c語言中的.h頭文件描述:

double    do_some_number_fudging(double a, int b);
myobj *   create_object();
double    do_stuff_with_object(myobj *obj);
void      use_string_with_object(myobj *obj, char *value);
void      delete_object(myobj *obj);

js中使用ffi進行對應描述:

var ffi = require("ffi");

var MyLibrary = ffi.Library('libmylibrary', {
  "do_some_number_fudging": [ 'double', [ 'double', 'int' ] ],
  "create_object": [ myobjPtr, [] ],
  "do_stuff_with_object": [ "double", [ myobjPtr ] ],
  "use_string_with_object": [ "void", [ myobjPtr, "string" ] ],
  "delete_object": [ "void", [ myobjPtr ] ]
});

然后,就可以在js中調用了:

var res = MyLibrary.do_some_number_fudging(1.5, 5);
var fun_object = MyLibrary.create_object();

if (fun_object.isNull()) {
    console.log("Oh no! Couldn't create object!\n");
} else {
    MyLibrary.use_string_with_object(fun_object, "Hello World!");
    var fun = MyLibrary.do_stuff_with_object(fun_object);
    MyLibrary.delete_object(fun_object);
}

感謝各位的閱讀,以上就是“怎么進行Node.js擴展開發(fā)”的內容了,經(jīng)過本文的學習后,相信大家對怎么進行Node.js擴展開發(fā)這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI