Запустить скрипт (например, postinstall) после установки npm одного пакета?

Я начинаю играть со Snowpack. Он использует другой подход, чем Webpack, объединяя отдельные пакеты сразу после их установки.

«Проблема» в том, что когда я устанавливаю пакет, мне нужно сначала запустить npm install --save my-package, а затем вручную упаковать его с помощью npx snowpack. В документах Snowpack упоминается, что я могу включить prepare скрипт, который будет snowpack выполнять все после работает npm install, но это не относится к отдельным пакетам, а только к общему npm install всех зависимостей в моем package.json. Насколько я могу судить, это относится ко всем хукам npm, упомянутым в документах по npm.

Есть ли способ автоматически запускать скрипт всякий раз, когда я устанавливаю отдельный пакет? Единственный способ, который я могу придумать, - это перезаписать сценарий установки и добавить в него что-то. Есть ли примеры этого на GitHub или где-либо еще?

Обновление: для пояснения, я хотел бы запускать npx snowpack каждый раз, когда я устанавливаю новый пакет с --save, но желательно не с --save-dev или без --save. Это никогда не будет отличаться для любого пакета. Это будет специфично для определенного репо/проекта, а не глобально в моей системе.

Недостаточно запустить snowpack после простого запуска npm install, как если бы вы подключились к postinstall или release. Кроме того, я хочу убедиться, что разработчики, работающие над моим проектом, могут использовать npm install --save newdep как обычно, а затем запустится snowpack. Я не хочу требовать, чтобы разработчики использовали собственный скрипт named.


person Brady Dowling    schedule 27.01.2020    source источник
comment
@RobC Хорошая мысль, хотя я не хочу связывать команды. Я опубликую здесь, когда у меня будет сценарий, который хорошо работает для этого.   -  person Brady Dowling    schedule 28.01.2020


Ответы (3)


Краткий ответ: К сожалению, npm не предоставляет никаких встроенных функций, отвечающих вашим требованиям.

Перехватчики/скрипты жизненного цикла, такие как postinstall, вызываются только при запуске универсального npm install, а не тогда, когда кто-то запускает npm install --save <pkg_name> на этапе разработки проектов.


Временное решение. Попробуйте настроить логику соединения npm install --save. команда, по существу переопределяя команду npm на уровне оболочки.

Следующее решение, хотя и основанное на Bash, описывает, как эта пользовательская логика может быть реализована для конкретного проекта (проектов). Однако это решение зависит от следующих условий:

  • Разработчики, работающие над вашим проектом, должны установить для своей оболочки Bash при выполнении составной команды npm install --save.
  • Разработчики, работающие над вашим проектом, должны будут настроить свои файлы запуска Bash., а именно ~/.bashrc и, возможно, ~/.bash_profile.
  • Каталог проекта, т. е. каталог проекта, для которого вы хотите, чтобы пользовательская логика работала, должен содержать пользовательский файл .bashrc.

Баш Решение:

Следующие три шага необходимы для настройки вашего проекта и операционных систем, чтобы при запуске разработчиком npm install --save <pkg_name> (или его вариантов) последовательно вызывалась команда npx snowpack.

Примечание. Пункты два и три (ниже) — это задачи, которые разработчики должны выполнить (один раз), чтобы настроить свои файлы запуска Bash.

  1. Файл .bashrc для конкретного проекта:

    Сначала создайте следующий специфичный для проекта файл .bashrc в корне каталога вашего проекта, т. е. сохраните его на том же уровне, где находится файл вашего проекта package.json:

    /some/path/to/my-project/.bashrc

    npm() {
    
      local name_badge="\x1b[37;40mpostinstall\x1b[0m"
    
      array_includes() {
        local word=$1
        shift
        for el in "$@"; do [[ "$el" == "$word" ]] && return 0; done
      }
    
      log_warn_message() {
        local cmd_name=$1 warn_badge warn_mssg
        warn_badge="\x1b[30;43mWARN!\x1b[0m"
        warn_mssg="${cmd_name} command not found. Cannot run npx snowpack."
        echo -e "\n${name_badge} ${warn_badge} ${warn_mssg}" >&2
      }
    
      log_run_message() {
        echo -e "\n${name_badge} Running pseudo postinstall hook."
      }
    
    
      if [[ $* == "install "* || $* == "i "* ]] && array_includes --save "$@"; then
    
        # 1. Run the given `npm install --save ...` command.
        command npm "$@"
    
        # 2. Check whether the `npx` command exists globally.
        command -v npx >/dev/null 2>&1 || {
          log_warn_message npx
          return 1
        }
    
        log_run_message
    
        # 3. Run the pseudo "postinstall" command.
        command npx snowpack
    
      else
        # Run all other `npm` commands as per normal.
        command npm "$@"
      fi
    }
    

    Примечание. Чтобы лучше понять, что делает этот файл, обратитесь к разделу Объяснение ниже.

  2. Файл ~/.bashrc:

    Чтобы сделать пользовательскую логику, то есть функцию npm в вышеупомянутом файле .bashrc, эффективной, необходимо настроить Bash для чтения вышеупомянутого специфического для проекта файла .bashrc. Чтобы настроить это, добавьте следующую строку кода в ~/.bashrc:

    PROMPT_COMMAND='if [[ "$bashrc" != "$PWD" && "$PWD" != "$HOME" && -e .bashrc ]]; then bashrc="$PWD"; . .bashrc; fi'
    

    Примечание. Чтобы лучше понять, что делает эта строка кода, обратитесь к разделу Объяснение ниже.

  3. Файл ~/.bash_profile:

    Обычно ваш ~/.bash_profile содержит следующую строку кода для загрузки файла ~/.bashrc (или его разновидности):

    if [ -f ~/.bashrc ]; then . ~/.bashrc; fi
    

    Если этого нет, то его нужно добавить к ~/.bash_profile.


Дополнительная информация.

Помощники по установке/конфигурации:

Подумайте о том, чтобы ваши разработчики использовали следующие две команды для облегчения настройки своих файлов запуска Bash в соответствии с вышеупомянутыми шагами два и три.

  1. Для шага два выполните следующую команду:

    echo $'\n'"PROMPT_COMMAND='if [[ \"\$bashrc\" != \"\$PWD\" && \"\$PWD\" != \"\$HOME\" && -e .bashrc ]]; then bashrc=\"\$PWD\"; . .bashrc; fi'" >> ~/.bashrc
    

    Это добавит строку кода PROMPT_COMMAND=... в существующий файл ~/.bashrc или создаст новую, если она еще не существует:

  2. На третьем шаге выполните следующую команду, чтобы добавить строку кода, необходимую в ~/.bash_profile для загрузки файла ~/.bashrc:

    echo $'\n'"if [ -f ~/.bashrc ]; then . ~/.bashrc; fi" >> ~/.bash_profile
    

Моя оболочка настроена на Bash?

Чтобы проверить, настроена ли оболочка для Bash, вы можете создать новый сеанс, т.е. создать новое окно терминала и запустить:

echo $0

Если он печатает -bash, значит, он использует Bash.

Как мне настроить мою оболочку для Bash?

Если echo $0 не печатает -bash, вам нужно изменить оболочку. Чтобы изменить его на Bash, выполните:

chsh -s /bin/bash

Примечание. Чтобы это изменение вступило в силу, вам потребуется создать новый сеанс.


Объяснение

  1. Файл .bashrc для конкретного проекта:

    Этот файл .bashrc содержит функцию оболочки. по имени npm. Тело этой функции содержит логику, необходимую для переопределения команды npm install|i --save по умолчанию.

    • Условия, указанные в операторе if, т. е. часть, которая читает;

      if [[ $* == "install "* || $* == "i "* ]] && array_includes --save "$@"; then
        ...
      fi
      

      по существу считывает $* специальный параметр в проверьте, начинаются ли аргументы, переданные функции npm, с любого; install или его сокращенный эквивалент i , а также была ли передана опция/аргумент --save.

      Чтобы проверить наличие аргумента --save, мы передаем специальный параметр $@ в функцию array_includes. Мы обрабатываем этот аргумент по-разному, потому что позиция параметра --save может отличаться в составной команде. Например, пользователь может установить пакет, запустив это;

      # Example showing `--save` option at the end
      npm install <pkg_name> --save
      

      или это (или какой-то другой вариант):

      # Example showing `--save` option in the middle
      npm i --save <pkg_name>
      
    • Когда условия, указанные в операторе if, выполняются, т.е. они true, мы выполняем следующие задачи в его теле:

      1. Запустите данную команду npm install --save ... как есть через строку, которая гласит:

        command npm "$@"
        
      2. Проверьте, существует ли глобально команда npx, через часть, которая гласит:

        command -v npx >/dev/null 2>&1 || {
          log_warn_message npx
          return 1
        }
        

        Если команда npx недоступна (глобально), мы предупреждаем пользователя, что команда npx snowpack не может быть запущена, и return из функции рано со статусом выхода 1.

        Примечание. Моя логика в этой проверке предполагает, что вы будете устанавливать npx глобально. Однако, если вы устанавливаете npm локально в своем проекте, вам нужно будет изменить эту логику. Возможно, проверив, существует ли ./node_modules/.bin/npx. Или вы можете быть уверены, что команда npx всегда будет существовать, поэтому сделайте вывод, что эта проверка не нужна.

      3. Если команда npx существует глобально, мы запускаем псевдокоманду postinstall, т.е.

        command npx snowpack
        
    • Когда условия, указанные в операторе if, НЕ выполняются, то есть они равны false, пользователь, по сути, запускает любую другую команду npm, отличную от npm install --save <pkg_name>. Поэтому в ветке else запускаем команду как есть:

      command npm "$@"
      
  2. Файл ~/.bashrc:

    В разделе 5.2 Переменные Bash Справочное руководство по Bash, переменная PROMPT_COMMAND описывается следующим образом:

    PROMPT_COMMAND

    Если установлено, значение интерпретируется как команда, которую необходимо выполнить перед печатью каждого основного приглашения ($PS1).

    Итак, эта строка кода (вот она снова):

    PROMPT_COMMAND='if [[ "$bashrc" != "$PWD" && "$PWD" != "$HOME" && -e .bashrc ]]; then bashrc="$PWD"; . .bashrc; fi'
    

    загружает специфичный для проекта .bashrc (если он существует), который, в свою очередь, переопределяет команду npm функцией npm. По сути, это обеспечивает механизм переопределения составной команды npm install --save для конкретного проекта(ов).

    См. этот ответ на @Cyrus для дальнейших объяснений.

person RobC    schedule 06.02.2020
comment
Столько времени и энергии ушло на этот ответ, но это явно слишком. Я не сомневаюсь в легитимности вашего ответа, это создаст эффект, за которым последует ОП. Просто подумайте о человеке, который продолжает свой проект, который не участвует. Кроме того, это не кроссплатформенная поддержка, но это действительно похоже на хорошее доказательство концепции того, что все возможно, еще раз. - person Martin Braun; 11.02.2020

В более новых версиях Snowpack (>=2) вы можете запустить snowpack dev, и он будет следить за вашей папкой npm_modules для сборки новых модулей.

person Brady Dowling    schedule 16.06.2020

Я думаю, что лучше всего было бы создать новый скрипт, который выполняет желаемое действие. Что-то вроде следующих строк в вашем package.json:

{
  "scripts": {
    "snowpack-install" : "npm install --save && npx snowpack"
  }
}

Коррекция

На самом деле вы можете использовать опцию постустановки в package.json. Постустановка запустится «ПОСЛЕ того, как пакет будет установлен». Это будет выглядеть примерно так:

{
  "scripts": {
    "postinstall" : "npx snowpack"
  }
}
person Greg    schedule 04.02.2020
comment
Я считаю, что postinstall запускается только после запуска общей формы npm install, так что это не будет делать то, что я ищу. Кроме того, я хотел бы избежать необходимости запускать какие-либо пользовательские именованные сценарии, поскольку это затруднит для товарищей по команде получение проекта и установку зависимостей. Уточню в вопросе. - person Brady Dowling; 04.02.2020
comment
Как насчет использования хуков NPM? blog.npmjs.org/post/145260155635/ - person Greg; 04.02.2020
comment
В этом случае кажется излишним вызывать внешний http-сервис (выходили ли хуки когда-нибудь из бета-версии?) - person Brady Dowling; 04.02.2020