node-pre-gyp 应用场景介绍及使用方法

Node.js 提供了使用 C++ addon 方案作为扩展的能力。我们可以编写 C++ 的代码来扩展 Node.js 或封装自己产品相关的能力接口为 Node.js 接口提供用户或者开发者使用。将编写好的源代码上传至 npm publish 平台,开发者通过 npm install 就可以使用你的扩展包了。但使用的前提是引入方必须要具备编译 C++ 代码的环境,比如在 Windows 下需要安装 MSVC 的编译工具链。而正常的前端开发者并不会将这些组件安装到系统里面,他们更关注的是前端业务逻辑。

由于 npm 平台不允许上传太大的文件或二进制文件,所以在用户执行 npm install 时自动下载已经预编译好的二进制文件包就映入我们的眼帘了。node-pre-gyp 就是来做这个用的。它包含了打包上传、根据版本自动下载等一系列流程。这些步骤只需要你对工程做一些简单的配置就可以实现。node-sqlite3 就是通过该插件来实现下载预编译的二进制包的:https://github.com/mapbox/node-sqlite3

针对一些不依赖三方 SDK 的 C++ 插件来说,只需导出一份 .node 文件即可让开发者导入使用。将二进制包打包为 .tar.gz,将打包后的压缩文件上传到外网可以访问的服务器中,接下来配置一下 node-pre-gyp 就可以了。首先安装 node-pre-gyp

npm install --save @mapbox/node-pre-gyp

创建一个新的 target action_after_build 用来在你主工程编译完成后自动拷贝 .node 文件到准备上传的目录:

{
    'target_name': 'action_after_build',
    'type': 'none',
    'dependencies': ['<(module_name)'],
    'copies': [
        {
            'conditions': [
                [
                    'OS=="win"',
                    {
                        'files': [
                            '<(PRODUCT_DIR)/<(module_name).node'
                        ],
                        'destination': '<(module_path)'
                    }
                ],
                [
                    'OS=="mac"',
                    {
                        'files': [
                            '<(PRODUCT_DIR)/<(module_name).node'
                        ],
                        'destination': '<(module_path)'
                    }
                ]
            ]
        }
    ]
}

配置 package.json,让 node-pre-gyp 知道编译后的包保存到什么位置,在 package.json 中新增如下字段:

"binary": {
    "module_name": "node_nim",
    "module_path": "./lib/binding/{node_abi}-{platform}-{arch}/",
    "remote_path": "./package/",
    "package_name": "{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz",
    "host": "https://your-download-host"
}

这里的 module_path 就是告诉 node-pre-gyp 编译后要保存到当前目录下的 ./lib/binding/{node_abi}-{platform}-{arch}/ 目录。目录名是根据当前环境来自动创建的。除了保存,上面的配置还告诉 node-pre-gyp 第三方程序引入这个包时,node-pre-gyp 会尝试从 ${host}/${remote_path}/${package_name} 去下载这个包。如果下载到了这个包,那么自动解压到 module_path 路径下,就不会再尝试编译了。

配置基本就绪,还差最重要的一步,替换默认的 npm install 流程:

"scripts": {
    "install": "node-pre-gyp install --fallback-to-build"
}

在你的 package.json 中,scripts 字段下添加 install 配置,让默认的 install 行为变为 node-pre-gyp install –fallback-to-build。这样在三方应用引入我们的包时会调用 node-pre-gyp install 首先到 package.json 中指定的 host 去尝试下载已经编译好的二进制包,如果没有下载到则调用本地的 node-gyp(注意这里不是 node-pre-gyp)根据外部传递的参数来从本地代码编译,这样也就串通了整个流程。

同时 node-pre-gyp 其实支持二进制包自动上传的能力,需要你单独配置 AWS3 的 token 等信息,由于国内访问 S3 资源很困难,这一步我们并没有做进一步验证,有兴趣的同学可以参考官方文档来尝试。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注