> 웹 프론트엔드 > JS 튜토리얼 > Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

青灯夜游
풀어 주다: 2022-08-29 20:04:57
앞으로
2304명이 탐색했습니다.

Node 확장 개발을 어떻게 수행하나요? 다음 기사에서는 Node.js 확장 개발을 위한 필수 지식을 소개하고 Node.js 확장 개발을 시작하는 데 도움이 될 것입니다. 모든 사람에게 도움이 되기를 바랍니다.

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

Node.js 확장을 개발하는 이유

1.Node.js는 CPU 집약적인 비즈니스에 적합하지 않습니다. 개발 확장은 비동기 계산을 위해 libuv 스레드 풀을 사용합니다

2. , 예를 들어 javascript보다 효율적인 c++, Rust 및 기타 언어를 사용합니다

3. 기존 C++ 라이브러리는 반복적인 개발을 피하기 위해 Node.js 확장으로 직접 캡슐화됩니다.

4. javascript Node.js 기능을 통해 달성할 수 없습니다

Node.js 확장자는 무엇입니까

Node.js 확장자는 파일 확장자가 .node인 바이너리 파일입니다. 본질적으로 동적 링크 라이브러리로 이해될 수 있습니다. .dll 또는 .so 파일로 이름이 변경됨, require

Node.js 모듈 공식 문서nodejs.cn/api/modules...

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

세 가지 형태의 Node.js 확장

으로 로드 가능
확장 유형 기본 설명 Node.js 버전 변경 시 코드 변경 Node.js 버전 변경 시 다시 컴파일
C++ 직접 작성 v8, libuv 및 기타 라이브러리를 직접 참조 개발
NAN 개발에 NAN(Native Abstraction for Node.js)을 사용하세요 아니요
N-API 개발에 node-addon-api를 사용하세요 아니요(ABI 버전은 일관성이 있어야 함) 아니요(ABI 버전은 일관성이 있어야 함)
直接写C++代码开发插件,当Node.js版本变化时引用的v8、libuv等库的版本可能发生变化,这些三方库的api也可能会变化,导致需要修改代码

NAN方式开发插件,引用nan.h需要在Node.js版本变化时重新编译

N-API方式调用Node.js稳定的二进制ABI接口(Application Binary Interface),只要ABI版本号一致就不需要重新编译复制代码
로그인 후 복사

我们可以从Node.js官网历史版本下载页面,NODE_MODULE_VERSION看到Node.js版本与ABI版本的对应关系,nodejs.org/zh-cn/downl…

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

或者执行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案例,引用的头文件不同。

3-Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

安装依赖项

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

3-Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

但是,公司内网环境一直安装失败,按照文档尝试改了各种参数还是失败,可能是公司内网环境问题。如果你也遇到类似问题,可以尝试手动安装依赖。 github.com/felixrieseb…

手动安装步骤如下:

1.安装node-gyp

npm install -g node-gyp
로그인 후 복사

2.安装Visual Studio Build Tools

可以参考node-gyp文档中的下载链接和步骤进行安装github.com/nodejs/node…

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

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

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

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版本号区分目录,例如:

C:\Users\z00443016\AppData\Local\node-gyp\Cache\18.0.0\include\node
로그인 후 복사

配置IDE时会需要用到,当前可以忽略,后续的文章会再介绍具体配置

3.安装python

官网下载地址:www.python.org/downloads/

安装完成后将python和python/Scripts/目录加入到Path环境变量

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

更新npm配置,

npm config set python D:\runtime\python复制代码
로그인 후 복사

从hellow world开始

以c++开发为例,复制官网示例到本地。github.com/nodejs/node…

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

执行npm install会自动调用node-gyp编译,生成build/Release/hello.node的目标文件,这个文件就是最终被js引用的扩展包,可以被require调用。

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

执行示例文件中的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'
로그인 후 복사

如需重新编译,可以执行node-gyp rebuild,或者执行node-gyp help了解其他命令

至此,一个Node.js扩展demo就完成了。

抛出问题

Node.js使用非阻塞io的方式,在一个线程内可以异步处理多个任务,但是如果有一个cpu密集型的任务一直在处理,那么就会阻塞其他任务,响应时间变长。

Node.js官网的解释如下 nodejs.cn/learn/the-n…

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

开发Node.js扩展是解决问题的方式之一,最终使用什么方式去解决问题,需要基于我们对Node.js的理解,找到最佳实践。在上述场景中,我们可以使用libuv提供的线程池来异步处理这些cpu消耗较高的任务,从而不会阻塞其他任务的执行。

Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

当然了,web server并不适合处理cpu密集型任务,如果这个cpu密集型的任务调用频繁且耗时较高,就需要考虑从业务维度拆分,将任务挪到消息队列消费端执行。

环境配置

vsCode安装c++ intelliSense扩展应用

1Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

配置.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扩展开发

可以参考官网示例,在项目中的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,执行npm install时会自动调用ndoe-gyp执行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预构建

由于编译是基于操作系统和硬件平台进行的,node-gyp构建生成的.node动态链接库不能跨平台,所以通常我们在使用Node.js扩展时以依赖包的形式引入项目,当执行npm install时,自动调用node-gyp生成当前环境可用的.node扩展包。

上述方式需要即时编译,无疑会拖慢npm install过程。于是就出现了node-pre-gyp预构建工具,直接从仓库下载当前环境可用的Node.js扩展包。

以Xprofiler为例,根据当前系统、硬件平台、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…

1Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

其他形式的扩展 napi-rs

rust语言非常火爆,在Node.js开发领域也大有成为基础设施的趋势。比如,Node.js作者的新项目Deno就是用rust语言开发的;使用swc开发的编译工具替代Babel提升性能;rust支持编译成Webassembly,在前后台都能执行,具有很好的前景。

很多公司对rust语言十分重视,例如下图中的TOP公司已经成为rust基金会白金会员,用实际行动支持rust语言的发展。foundation.rust-lang.org/

1Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유

类似c++项目使用napi开发Node.js扩展,社区出现了napi-rs项目来支持rust语言开发Node.js扩展。github.com/napi-rs/nap…

直接调用动态链接库 node-ffi

FFI(Foreign Function Interface)语言交互接口,用一种编程语言写的程序能调用另一种编程语言写的函数,基本上成熟的编程语言都支持。使得我们可以在Node.js中直接调用c/c++、go、rust等语言编译生成的动态链接库,示例如下: github.com/node-ffi/no…

例如libmylibrary.dll或libmylibrary.so动态链接库的代码,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相关知识,请访问:nodejs 教程

위 내용은 Node.js 확장을 개발하는 방법은 무엇입니까? 사전 지식 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿