node gyp安装canvas原生模块编译node pregyp详解

目录
  • 关于node-gyp
  • node-pre-gyp
  • canvas安装过程追踪
    • 1. 安装canvas
    • 2. canvas的package的命令脚本
    • 3. node-pre-gyp install命令
    • 4. 下载预构建的二进制文件
  • 让node-pre-gyp通过淘宝源下载预构建文件

关于node-gyp

node-gyp是一个用 Node.js 编写的跨平台命令行工具,用于为 Node.js 编译本机插件模块。它包含之前由 Chromium 团队使用的 gyp-next项目的供应副本,扩展以支持 Node.js 原生插件的开发。

node-gyp is a cross-platform command-line tool written in Node.js for compiling native addon modules for Node.js. It contains a vendored copy of the gyp-next project that was previously used by the Chromium team, extended to support the development of Node.js native addons.

node是跨平台的,那么对于任何的node模块理论也是应该是跨平台的。然而,有些node模块直接或间接使用原生C/C++代码,这些东西要跨平台,就需要使用源码根据实际的操作平台环境进行原生模块编译。通常我们开发环境为macOS或Windows,而生产环境为Linux的各种发行版,这将导致我们的开发工作变得沉重不堪。那我们是否可以跳过node-gyp的编译过程?

node-pre-gyp

node-gyp的编译是让人难受的过程,所以社区出现了node-pre-gypprebuild-install,它们都会优先下载插件作者预编译的二进制文件,当二进制文件下载出现问题时,再使用node-gyp进行编译兜底。

但因为我们网络环境的特殊性,这些二进制文件我们大概率是不会下载成功的,接下来一起来看看在canvas的安装过程中node-pre-gyp干了什么事。

关于prebuild-install参考姊妹文【Nodejs】关于原生模块编译node-gyp + prebuild-install (以安装 better-sqlite3为例)

canvas安装过程追踪

canvas就使用了node-pre-gyp来优化构建过程

1. 安装canvas

关于install我们需要了解一点东西, 通常基于表象我们都会认为npm下载解压并释放到node_modules后就完成了安装过程,但实际上npm还会检查package中是否配置了install命令,存在就会立即执行,这也是原生模块在下载完成后会自动构建的基础。

npm install canvas

2. canvas的package的命令脚本

可以看到canvas配置了install命令,所以npm下载canvas后立即执行了

node-pre-gyp install --fallback-to-build --update-binary

{
    ...,
    "scripts": {
        "prebenchmark": "node-gyp build",
        "benchmark": "node benchmarks/run.js",
        "lint": "standard examples/*.js test/server.js test/public/*.js benchmarks/run.js lib/context2d.js util/has_lib.js browser.js index.js",
        "test": "mocha test/*.test.js",
        "pretest-server": "node-gyp build",
        "test-server": "node test/server.js",
        "generate-wpt": "node ./test/wpt/generate.js",
        "test-wpt": "mocha test/wpt/generated/*.js",
        "install": "node-pre-gyp install --fallback-to-build --update-binary",
        "dtslint": "dtslint types"
    }
}

3. node-pre-gyp install命令

node-pre-gyp命令最终链接到了@mapbox/node-pre-gyp/lib/main.js,根据参数install最终进入@mapbox/node-pre-gyp/lib/install.js执行

4. 下载预构建的二进制文件

可以看到node-pre-gyp先检查项目本地是否已经存在二进制构建文件,当不存在时进入用户本地查找,当用户本地也不存在时会执行http下载任何,接下来我们在看看http链接如何生成

existsAsync(binary_module, (found) => {
      if (!update_binary) {
        if (found) {
          console.log('[' + package_json.name + '] Success: "' + binary_module + '" already installed');
          console.log('Pass --update-binary to reinstall or --build-from-source to recompile');
          return callback();
        }
        log.info('check', 'checked for "' + binary_module + '" (not found)');
      }
      makeDir(to).then(() => {
        const fileName = from.startsWith('file://') && from.slice('file://'.length);
        if (fileName) {
          extract_from_local(fileName, to, after_place);
        } else {
          place_binary(from, to, opts, after_place);
        }
      }).catch((err) => {
        after_place(err);
      });
      function after_place(err) {
        if (err && should_do_fallback_build) {
          print_fallback_error(err, opts, package_json);
          return do_build(gyp, argv, callback);
        } else if (err) {
          return callback(err);
        } else {
          console.log('[' + package_json.name + '] Success: "' + binary_module + '" is installed via remote');
          return callback();
        }
      }
    });

其中from变量即预构件二进制文件地址,指向opts.hosted_tarball,源码只保留了核心部分,完整源码请查阅@mapbox/node-pre-gyp/lib/util/versioning.js

const host = process.env['npm_config_' + validModuleName + '_binary_host_mirror'] || package_json.binary.host;
opts.host = fix_slashes(eval_template(host, opts));
...
opts.remote_path = package_json.binary.remote_path ? drop_double_slashes(fix_slashes(eval_template(package_json.binary.remote_path, opts))) : default_remote_path;
...
opts.hosted_path = url.resolve(opts.host, opts.remote_path);
opts.hosted_tarball = url.resolve(opts.hosted_path, opts.package_name);

可以看到node-pre-gyp会读取配置文件中是否配置了{包名}_binary_host_mirror,否则读取待构建的插件package.json中的binary.host配置项,所以在prebuild-install中可以生效的{p包名}_binary_host在node-pre-gyp中是无效的,所以针对原生插件我们需要查看插件使用的node-pre-gyp还是prebuild-install来灵活调整.npmrc中的预构件二进制文件下载镜像源

让node-pre-gyp通过淘宝源下载预构建文件

npm提供了.npmrc配置文件并注入到进程的env环境变量中,从上面的源码可知,node-pre-gyp会优先读取npm_config_{包名}_binary_host_mirror(.npmrc中的变量均会被npm添加npm_config_前缀, 所以我们配置时无需添加npm_config_前缀),另外需要值得注意的是npm会将.npmrc中的键以下划线的方式组织且任何非数字和字母的字符将会被替换为_。所以以canvas举例来说,配置如下

canvas_binary_host_mirror=https://registry.npmmirror.com/-/binary/canvas

鉴于prebuild-install兼容性更好,针对原生模块我们在.npmrc中以{包名}_binary_host_mirror={mirror}的格式配置预构建文件下载镜像

以上就是node gyp安装canvas原生模块编译node pregyp详解的详细内容,更多关于node gyp安装canvas的资料请关注我们其它相关文章!

(0)

相关推荐

  • nodejs npm install全局安装和本地安装的区别

    npm的包安装分为本地安装(local).全局安装(global)两种,从敲的命令行来看,差别只是有没有-g而已,比如: 复制代码 代码如下: npm install grunt # 本地安装npm install -g grunt-cli # 全局安装 下面分别解释. 1. npm install xxx -g 时, 模块将被下载安装到[全局目录]中. [全局目录]通过 npm config set prefix "目录路径" 来设置. 通过 npm config get prefi

  • node.js使用npm 安装插件时提示install Error: ENOENT报错的解决方法

    在使用npm install安装扩展插件时,系统提示"npm install Error: ENOENT, stat 'C:Users<用户名>AppDataRoamingnpm'". 以前都是很顺利的安装过程,没出现这种情况.我这里的解决办法是直接创建上面提示的目录就好了,应该是node.js权限不够,在此备注. 有时候就是这样,很可能一个很久都无法解决的问题,实际解决方法很简单,就是这么任性!!

  • npm install --save 、--save-dev 、-D、-S 的区别与NODE_ENV的配置方法

    目录 1.npm install <=> npm i 2.npm i --save-dev <packname> 3.npm i --save <packname> 4.对应关系如下 5.使用npm i 安装package.json里的依赖时,两部分的包都会pull下来 备注:<=> 意为等价于: 1.npm install <=> npm i --save <=> -S --save-dev <=> -D npm run

  • node gyp安装canvas原生模块编译node pregyp详解

    目录 关于node-gyp node-pre-gyp canvas安装过程追踪 1. 安装canvas 2. canvas的package的命令脚本 3. node-pre-gyp install命令 4. 下载预构建的二进制文件 让node-pre-gyp通过淘宝源下载预构建文件 关于node-gyp node-gyp是一个用 Node.js 编写的跨平台命令行工具,用于为 Node.js 编译本机插件模块.它包含之前由 Chromium 团队使用的 gyp-next项目的供应副本,扩展以支持

  • 关于pip的安装,更新,卸载模块以及使用方法(详解)

    在Python的学习过程中,肯定会遇到很多安装模块的地方,可以使用easy_install安装,但是easy_install相对于pip而言,最大的缺陷就是它所安装的模块是不能够卸载的,其他功能是和pip一样的. 下面介绍一下pip的安装: 安装我总结了两个方法 1 通过下载安装文件来安装 2 通过easy_install安装 1 下载pip安装包 https://pypi.python.org/pypi/pip#downloads 1) 网页提供了两个安装包,一个是.whl的 一个是压缩包的,

  • Node.js学习之地址解析模块URL的使用详解

    前言 本文主要给大家介绍了关于Node.js地址解析模块URL使用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. url结构化/模块化/路径解析 结构化:url.parse(urlString[, parseQueryString[, slashesDenoteHost]]) 模块化:url.format(urlObject) 路径解析:url.resolve(from, to) 一个URL字符串是一个结构化的字符串包含多个有意义的组件.在解析时,返回一个URL对象

  • Node.js实战之Buffer和Stream模块系统深入剖析详解

    目录 正文 写入缓冲区 从流中读取数据 管道流 链式流 模块系统 正文 JavaScript语言本身只有字符串数据类型,没有二进制数据类型. 但是,在处理TCP流或文件流时必须使用二进制数据. 因此,在node JS中,定义了一个缓冲区类来创建用于存储二进制数据的缓冲区. const buf = Buffer.from('runoob', 'ascii'); 在node JS中,缓冲区类是与node内核一起发布的核心库. 缓冲库是node JS带来的一种存储原始数据的方法,它允许节点JS. co

  • Linux使用Node.js建立访问静态网页的服务实例详解

    Linux使用Node.js建立访问静态网页的服务实例详解 一.安装node.js运行所需要的环境,:http://www.jb51.net/article/79536.htm 二.创建node目录(/node/www),并在目录下创建node.js服务文件server.js var http = require('http'); var fs = require('fs');//引入文件读取模块 var documentRoot = '/node/www';//需要访问的文件的存放目录 var

  • Node.js基础入门之使用方式及模块化详解

    目录 什么是Node.js ? Node.js下载 Node.js和JavaScript的区别 Node.js安装与验证 Node.js使用方式 1. REPL模式 2. 文件模式 Node.js模块化 1. 什么是模块? 2. 模块分类 3. 创建自定义模块 4. 调用自定义模块 5. 模块测试 6. 主模块 7. 模块组成 在这个竞争日益激烈的今天,已经不是一门语言,一项技术走天下的时代了.正所谓艺多不压身,今天开始学习Node.js,学而时习之,不亦乐乎,希望可以借鉴经验,学以致用,如有不

  • node.js根据不同请求路径返回不同数据详解流程

    目录 1.学习根据不同的请求路径返回:不同数据 2.发送的数据:数据类型,和什么编码:Content-Type 3.关于读入文件的:相对路径和绝对路径: 4.读图片 1.学习根据不同的请求路径返回:不同数据 var url=req.url //获取req.url值(req:是request简写) req.url: 获取的是端口号之后的路径 实现不同路径返回不同数据 我的端口号:3000,网址:http://127.0.0.1:3000 if(url==='/'){ res.end('index

  • node后端与Vue前端跨域处理方法详解

    目录 node.js后端跨域解决方案 前端vue项目 前端axios请求 node.js后端跨域解决方案 先看后端的入口文件: app.js const express = require('express'); const bodyParser = require('body-parser'); const cors = require('cors') const expressJWT = require('express-jwt') const app = express(); const

  • ubuntu 16.04安装redis的两种方式教程详解(apt和编译方式)

    ubuntu 16.04安装redis的两种方式教程如下所示: 方式一 :apt安装 在 Ubuntu 系统安装 Redi 可以使用以下命令: $sudo apt-get update $sudo apt-get install redis-server 启动 Redis $ redis-server 查看 redis 是否启动? $ redis-cli 以上命令将打开以下终端: redis 127.0.0.1:6379> 127.0.0.1 是本机 IP ,6379 是 redis 服务端口.

  • node.js事件循环机制及与js区别详解

    目录 一.是什么 二.流程 三.题目 一.是什么 在浏览器事件循环(opens new window)中,我们了解到javascript在浏览器中的事件循环机制,其是根据HTML5定义的规范来实现 而在NodeJS中,事件循环是基于libuv实现,libuv是一个多平台的专注于异步IO的库,如下图最右侧所示: 上图EVENT_QUEUE 给人看起来只有一个队列,但EventLoop存在6个阶段,每个阶段都有对应的一个先进先出的回调队列 二.流程 上节讲到事件循环分成了六个阶段,对应如下: tim

随机推荐