На этой странице

Одно из ограничений нативных аддонов в том, что их нужно компилировать под каждую целевую платформу и архитектуру. Без готовых бинарников каждый пользователь, устанавливающий ваш пакет, должен иметь рабочий C/C++-тулчейн на своей машине.

node-pre-gyp решает это, позволяя вам собирать бинарники заранее, загружать их в удалённое место и давать пользователям скачивать нужный бинарник во время установки — откатываясь к компиляции из исходников только если подходящего бинарника нет.

Обратите внимание, что поддержка Node-API была добавлена в node-pre-gyp в версии 0.8.0.

Эта страница описывает изменения, необходимые Node-API-аддону для поддержки node-pre-gyp.

По умолчанию node-pre-gyp загружает бинарники в Amazon S3.

Модуль node-pre-gyp-github добавляет поддержку публикации в GitHub Releases вместо этого.

Перед загрузкой вам нужны:

  1. Аккаунт Amazon Web Services.
  2. IAM-пользователь или роль с правом загрузки в S3.
  3. S3-бакет для хостинга бинарников.

Никогда не храните учётные данные в своём репозитории. node-pre-gyp поддерживает два распространённых подхода к предоставлению учётных данных во время разработки:

  1. Файл ~/.node_pre_gyprc:

    {
      "accessKeyId": "xxx",
      "secretAccessKey": "xxx"
    }
  2. Переменные окружения:

    export node_pre_gyp_accessKeyId=xxx
    export node_pre_gyp_secretAccessKey=xxx

Для CI-окружений предпочитайте IAM-роли или короткоживущие учётные данные, а не долгоживущие ключи доступа. Дополнительные варианты см. в документации node-pre-gyp по учётным данным.

Пакет теперь публикуется в скоупе @mapbox. Используйте @aws-sdk/client-s3 как dev-зависимость для шага загрузки.

"dependencies": {
  "@mapbox/node-pre-gyp": "^1.0.0"
},
"devDependencies": {
  "@aws-sdk/client-s3": "^3.0.0"
}

Скрипт install должен вызывать node-pre-gyp с --fallback-to-build, чтобы пользователи, у которых нет доступного готового бинарника, всё же могли скомпилировать локально:

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

Свойство binary говорит node-pre-gyp, какие версии Node-API поддерживает ваш аддон и где искать/загружать бинарники:

"binary": {
  "module_name": "your_module",
  "module_path": "./lib/binding/napi-v{napi_build_version}",
  "remote_path": "./{module_name}/v{version}/{configuration}/",
  "package_name": "{platform}-{arch}-napi-v{napi_build_version}.tar.gz",
  "host": "https://your_bucket.s3.us-west-1.amazonaws.com",
  "napi_versions": [3]
}

Установите module_name в валидный идентификатор C. Массив napi_versions перечисляет, под какие версии Node-API собирать; 3 — разумный минимум для большинства аддонов.

Полный справочник, включая соображения по Node-API, см. в документации node-pre-gyp.

Добавьте post-build target, чтобы скопировать скомпилированный бинарник по пути, указанному в module_path:

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

Включите версию Node-API в defines первого target'а, чтобы заголовочные файлы правильно себя сконфигурировали:

"defines": [
  "NAPI_VERSION=<(napi_build_version)"
]

JavaScript-код, загружающий нативный бинарник, должен динамически разрешать путь к правильному файлу .node:

const binary = require('@mapbox/node-pre-gyp');
const path = require('path');
const bindingPath = binary.find(
  path.resolve(path.join(__dirname, './package.json'))
);
const binding = require(bindingPath);

Как только всё на месте, соберите из исходников:

./node_modules/.bin/node-pre-gyp package
./node_modules/.bin/node-pre-gyp publish

Используйте GitHub Actions, чтобы собирать, тестировать и публиковать бинарники для нескольких платформ и архитектур. Типичная матрица workflow покрывает ubuntu-latest, macos-latest и windows-latest, плюс любые нужные вам варианты архитектуры (например, x64, arm64). Примеры конфигураций workflow см. в репозитории node-pre-gyp.