Лучшая практика для обновления npm `prepublish` script для npm @>= 4

Я запускаю npm install из корневую папку моего образца проекта для ее создания с использованием сценариев в package.json.

В сборке требуется несколько шагов транспиляции в настоящее время в prepublish script, но версия npm версии 4 отображает предупреждение о том, что происходит изменение прерывания, что заставило меня поверить в новый prepare событие сборки script - более надежное будущее.

C:\code\antlr4ts-json>npm install
npm WARN prepublish-on-install As of [email protected], `prepublish` scripts will run only for `npm publish`.
npm WARN prepublish-on-install (In [email protected] and previous versions, it also runs for `npm install`.)
npm WARN prepublish-on-install See the deprecation note in `npm help scripts` for more information.
...

К сожалению, просто перемещение script от prepublish до prepare прерывает обратную совместимость: если кто-то запускает npm install с помощью [email protected], шаги сборки в prepare молча игнорируются.

Что лучше всего подходит для обновления моего времени сборки script? В идеале я хотел бы обновить свой package.json, чтобы npm install работал для любого npm @ >= 3, но в качестве альтернативы генерирует ясное сообщение об ошибке, указывающее, что npm @ >= 4 требуется при запуске npm install с использованием npm @3.

Bakground: Я пытался включить

"engines": { "npm":  ">=4.0.0" },

Благодаря @toomuchdesign (и другим), я понимаю, почему это не делает то, что я хочу; engines проверяет только, когда мой пакет установлен как зависимость, а не кто-то создает его из источников. Это имеет смысл.

Я отслеживал предысторию этого запланированного изменения до npm issue # 10074, что объясняет, почему необходимо изменить разрыв. Однако я все еще не понимаю, как лучше справляться с переходом.

Ответы

Ответ 1

Я нашел лучшее решение, используя check-node-version; этот пакет имеет интерфейс командной строки, что упрощает его использование для этой цели. Вот шаги, которые я бы предложил в качестве наилучшей практики:

  • Добавьте зависимость развития с помощью npm install -D [email protected],
  • Переименуйте существующий prepublish script в prepare,
  • Добавьте замену prepublish script для обратной совместимости и предложите обновить npm (см. ниже).

Мой package.json теперь выглядит примерно так:

"scripts": {
    "prepare": "npm run antlr4 && tsc",
    "prepublish": "check-node-version --npm \">=4\" || npm run prepare",
    "antlr4": "rimraf gen && antlr4ts Json.g4 -o gen -visitor",
    ...
},
"devDependencies": {
    "check-node-version": "^1.1.2",
    ...

При таком подходе:

  • npm install всегда запускается prepare script, даже с установленным [email protected]. Это должно работать правильно, если [email protected] установлен (непроверен.)

  • В [email protected] есть даже полезное сообщение об обновлении npm, но поскольку script использует || npm run prepare для имитации поведения более поздних версий, script продолжается после ошибки.

  • Если позже мне понадобится жесткая зависимость от [email protected], удаление части || npm run prepare приведет к остановке script, если она запущена на [email protected].

Вот что выглядит построение с помощью [email protected]:

C:\code\antlr4ts-json>npm i

> [email protected] prepublish C:\code\antlr4ts-json
> check-node-version --npm ">=4" || npm run prepare

node: v6.9.1
npm: v3.10.10
Error: Wanted npm version ">=4" (>=4.0.0)
To install npm, run `npm install -g [email protected]>=4`

> [email protected] prepare C:\code\antlr4ts-json
> npm run antlr4 && tsc

Ответ 2

NPM docs утверждают, что поле engines выдает ошибку только тогда, когда ваш пакет установлен как зависимость:

Если пользователь не установил флаг конфигурации engine-strict, поле [двигатели] является рекомендательным, будет выдавать предупреждения, когда ваш пакет установлен как зависимость.

Как разработчик /mantainer проекта, вы не должны видеть никаких предупреждений из вашего поля engines.

Поскольку вам нужно скомпилировать ваши файлы при запуске только npm install, вы можете просто использовать postinstall hook.

Также обратите внимание, что prepublish останется, он просто изменит свое поведение на [email protected], выстрелив только до publish hook.