node-gyp是generate your projects的缩写,是一个让我们为Node.js构建本地插件的工具。由于历史原因(我们将在本文中概述),使用node-gyp很容易导致难以解决的问题。
在这篇文章中,我们将node-gyp的所有主要问题归为三类,包括node-gyp的依赖性、附加组件编译错误和绑定契约违反。我们将逐一审查每个类别,并沿途提供解决方案。
如果你还不熟悉node-gyp或者自己没有遇到过这些问题,我建议你先看看项目的README文件。让我们开始吧!
node-gyp的依赖性
在我们开始之前,需要注意的是,如果你安装了Node.js,你可能已经安装了node-gyp,但没有全局暴露。如果你只需要在项目设置过程中编译附加组件,Node.js应该为你覆盖。然而,如果你是一个附加组件的开发者,你可能需要全局安装node-gyp。
为了使用node-gyp,首先,我们需要安装Python运行时、make 工具以及C或C++编译器。node-gyp 希望 Python ≥v3.6,而不是 Python v2.x。如果你不是一个 Python 开发者,你可能没有意识到 Python v.3 并不向后兼容它以前的主要版本。
此外,许多现代操作系统在第一次启动时就提供了默认的运行时,然而,这些运行时可能不符合 node-gyp 的要求。在开始使用node-gyp之前,请确保为你的系统正确地安装正确的依赖性。
最后,许多软件开发者倾向于忽略CPU架构,经常假设x86指令集的64位版本可以工作。但随着新的CPU不断出现在市场上,这与事实相去甚远。
附加组件的编译错误
通常情况下,开发者用C语言和N-API绑定或C++语言和NAN绑定来编写Node.js的附加组件。我们稍后会深入讨论绑定问题,但现在请记住,至少有两种方法可以将附加组件的代码与Node.js的运行时间连接起来。
通常,当你安装一个使用node-gyp的外部依赖时,node-gyp会下载与你的架构和你系统上的Node.js版本相匹配的预建二进制文件。node-gyp只有在没有找到匹配的时候才会编译附加代码,这可能会导致问题。
大多数编程语言都是向后兼容的,或者至少有一个小的发布版本是兼容的。想象一下,一个附加组件的作者写了代码,但使用的语言版本比你的系统支持的版本高。你就根本无法编译该附加组件。
为了解决编译错误,你可以分叉其代码库或升级或降级你的编译器工具链。
违反绑定合同
之前,我们提到了两种类型的绑定,NAN,Node.js的本地抽象,以及Node-API,以前被称为N-API。第三种类型的绑定包括V8、libuv和Node.js头文件。
V8是一个由Node.js使用的JavaScript和WebAssembly引擎。Libuv是Node.js使用的一个C库,以获得对异步I/O的支持。
第一种绑定方法,即NAN,提供头文件,使附加组件能够直接与V8运行时进行交互。它类似于使用普通的V8头文件,只是有额外的预防措施。由于每个Node.js版本都可能使用不同的V8版本,使用NAN的附加组件间接地依赖于其用户所使用的V8版本。
如果一个附加组件的代码期望从V8获得比它所提供的更多或不同的功能,那么该附加组件在链接阶段可能会失败。或者更糟的是,连接可能成功,但由于头文件不正确,附加组件在运行时崩溃。
为了弥补这些缺陷,Node.js现在暴露了Node-API,一个独立于JavaScript运行时的稳定的API。然而,这种方法也并不完美。目标Node版本需要在附加组件使用的版本中实现Node-API。要知道你可以针对某个特定的Node.js安装使用哪个版本的Node-API,你应该查看版本矩阵。
遗憾的是,对于违反绑定合同的行为,没有简单的解决办法。如果你是代码的作者,你可以调整它,否则,你可能需要升级或降级你的Node.js版本。在文章的后面,我们将介绍一些更通用的方法来处理类似问题。
问题分类
你可能已经意识到,报告为node-gyp问题的问题,实际上是用于构建附加代码的工具链的问题。现在,让我们来介绍一下如何对问题进行分类以应用正确的解决方案。当你遇到一个问题时,你可以问自己以下问题。
- 问题报告者是谁?是附加组件的发布者还是附加组件的消费者?
- 你的机器的架构和工具链是什么?
- 目标Node.js版本是什么?
- 附加组件是使用NAN还是Node-API?
- 附加组件使用哪种编程语言?
简单地说,在修复潜在问题时,附加组件发布者比消费者有更多的工具可以使用。架构和工具链影响整个构建过程。目标Node.js版本可能会损害NAN的合作方式,有些低版本不支持Node-API。附加组件的编程语言会影响Node和NAN/Node-API绑定的接触点。
值得注意的是,一个使用node-gyp构建的附加组件的安装可能会引发许多问题,每个问题都属于不同的类别。
检查架构和工具链
检查架构和工具链需要了解你机器的软件和硬件。你应该获得关于你的操作系统和CPU/GPU的信息。你很可能工作在一个与x86-64兼容的指令集上,但最好还是验证一下这个信息。
要检查当前在你的终端上使用的Python 3的版本,运行下面的命令。
python3 --version
在你的终端,运行下面的命令来检查你使用的C/C++编译器工具链的版本。
gcc --version
要检查你机器上的Node.js版本,使用下面的代码。
node --version
你可以用一个Node.js版本管理器动态地改变执行的Node.js版本,比如Linux和macOS上可用的n,或者nvm。然而,为了避免以自动化的方式使用每个工具,这可能会导致我们之前列出的一些问题,我们将检查附加组件的绑定情况。
检查附加组件的绑定
我们需要访问上述附加组件的代码库。我们需要查看的最重要的文件是binding.gyp 文件,通常位于附加组件的根目录中。我们应该搜索其中所有的require 语句;require("nan") 表示该附加组件使用NAN,而require("node-addon-api") 表示该附加组件使用Node-API。
为了进一步说明,你可以在GitHub上看到NAN和Node-API中的binding.gyp 文件的例子。
我们还可以在整个项目中搜索NAN或Node-API的宏,#include <nan.h> 和#include <node_api.h> 。有些项目也可能使用V8头文件,这些文件使用#include <v8.h> 宏。
检查编程语言
你应该通过文件名的扩展名看到编程语言。C语言的头文件使用.h ,源文件使用.c 。另一方面,C++的头文件使用.h,.hpp, 和.hxx ,源文件使用.cpp 和.cxx 。
使用node-addon-api 模块的附加组件是C++项目。否则,在不打算使用C++封装类的情况下,获得C++封装类的声明是毫无意义的。
通用的故障排除策略
此时,如果你已经实施了上述解决方案,但仍然没有解决你所面临的问题,我们准备了一些通用的想法来尝试。
设置Node.js环境和node-gyp依赖项在你的操作系统上可能并不直接。作为一个替代方案,让我们尝试在Docker镜像中而不是在你的本地机器中构建附加组件,让你控制所有的依赖,包括操作系统。如果你能构建Docker镜像,但在你的本地设置中仍有问题,你就会知道问题出在哪里。
作为一个例子,我们准备了以下Docker文件片段,它在Alpine Linux实例上构建了SQLite3插件。
FROM alpine:3.14.2
RUN apk update
RUN apk add --no-cache \
build-base \
curl \
git \
linux-headers \
nodejs \
npm \
py3-pip \
python3 \
python3-dev \
sqlite
RUN pip3 install --upgrade pip
WORKDIR /opt/showcase
RUN npm init -y
RUN apk add sqlite
RUN npm install sqlite3 --verbose --build-from-source
你可以在你选择的目录中把它保存为Dockerfile ,然后用docker build .
我们使用Alpine Linux是因为它的轻量级特性。你可能已经注意到,我们不得不手工添加我们的依赖项。作为一个练习,你可以删除一些依赖项,看看每个依赖项对SQLite3的安装有何影响。此外,你可以检查一下建议的node-rdkafka的Docker文件,尽管它有些过时。
你也可以尝试改变Docker镜像内的架构,例如,你可以选择32位版本的Ubuntu。我们相信你可以把这个提示用于老项目,但请注意,你在32位的主机上运行64位的虚拟化操作系统是相当不可能的。
使用Docker升级或降级Node.js版本是很简单的。为了加快这一过程,Node.js Docker团队提供了不同版本的Docker镜像。
如果你能接触到基于NAN的插件的代码库,你可以尝试切换到Node-API。这需要你事先有编写附加组件的经验。你也应该有足够的资源来承担这样的任务。
结论和资源
希望在本教程结束时,你已经能够解决你的node-gyp问题。我们学会了如何通过提出一系列问题将问题分为三个常见的类别,然后针对每个类别提供独特的解决方案。然后我们为node-gyp问题提供了一个更通用的、普遍的解决方案,即使用Docker文件。
在极少数情况下,如果上面提出的步骤对你不起作用,你可以浏览以下资源和支持渠道。我希望你喜欢这个教程,并对node-gyp有了更深刻的理解。
资源。
支持。
The post Solvingcommon issues with node-gypappeared first onLogRocket Blog.