在npm安装单个软件包后运行脚本(如postinstall)?

时间:2020-01-27 15:55:47

标签: npm snowpack

我开始玩Snowpack。与Webpack相比,它采取了与Webpack不同的方法,即在安装各个软件包后立即捆绑它们。

“问题”是,当我安装软件包时,我必须首先运行npm install --save my-package,然后必须手动将其与npx snowpack一起打包。 Snowpack docs提到,我可以包含一个prepare脚本,该脚本将在运行snowpacknpm install进行所有操作,但不适用于单个软件包,仅适用于通用{{1 }} npm install中的所有依赖项。据我所知,npm docs中提到的所有npm挂钩都是这种情况。

安装单个软件包时,有什么方法可以自动运行脚本吗?我能想到的唯一方法是覆盖安装脚本并向其中添加一些内容。在GitHub或其他地方有任何示例吗?

更新:为澄清起见,我每次安装带有package.json的新软件包时都希望运行npx snowpack,但最好不要安装--save --save-dev。这对于任何软件包都不会有什么不同。这将特定于某个回购/项目,而不是系统上的全局项目。

仅运行--save之后运行snowpack是不够的,就像您迷上了npm installpostinstall一样。另外,我想确保从事我的项目的开发人员可以像往常一样使用release,然后运行npm install --save newdep。我不想要求开发人员使用自定义的命名脚本。

3 个答案:

答案 0 :(得分:5)

简短答案::不幸的是,npm不提供任何内置功能来满足您的要求。

诸如postinstall之类的生命周期挂钩/脚本仅在运行通用npm install命令时被调用,而在项目开发阶段仅当某人运行npm install --save <pkg_name>时才被调用。


解决方法:考虑通过在外壳层级别实质上覆盖npm命令来定制npm install --save复合命令的逻辑。

以下解决方案(尽管是Bash解决方案)描述了如何针对特定项目实现这种自定义逻辑。但是,此解决方案取决于以下条件:

  • 在运行npm install --save复合命令时,从事项目工作的开发人员必须将shell设置为Bash
  • 从事您的项目的开发人员将需要自定义其Bash startup files,即~/.bashrc,甚至可能是~/.bash_profile
  • 项目目录,即您要使自定义逻辑生效的项目目录,必须包含自定义.bashrc文件。

Bash解决方案:

以下三个步骤是配置项目和操作系统所必需的,因此,当开发人员运行npm install --save <pkg_name>(或其变体)时,npx snowpack命令随后被调用。 / p>

注意:第二点和第三点(下面)是开发人员执行(一次)自定义其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配置为读取上述“特定于项目” { {1}}文件。要进行配置,请将以下代码行添加到.bashrc

    ~/.bashrc

    注意:为了更好地理解此代码行的内容,请参见下面的“说明” 部分。

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

    通常,您的~/.bash_profile包含以下代码行,用于加载~/.bash_profile文件(或其某些变体):

    ~/.bashrc

    如果不存在,则必须将其添加到if [ -f ~/.bashrc ]; then . ~/.bashrc; fi


其他信息。

设置/配置助手:

根据上述第二步和第三步,考虑使用以下两个命令帮助开发人员配置Bash启动文件。

  1. 对于第二步,运行以下命令:

    ~/.bash_profile

    这会将echo $'\n'"PROMPT_COMMAND='if [[ \"\$bashrc\" != \"\$PWD\" && \"\$PWD\" != \"\$HOME\" && -e .bashrc ]]; then bashrc=\"\$PWD\"; . .bashrc; fi'" >> ~/.bashrc 行代码添加到现有的PROMPT_COMMAND=...文件中,或者如果尚不存在,则创建一个新文件:

  2. 对于第三步,运行以下命令以在~/.bashrc中添加用于加载~/.bash_profile文件的代码行:

    ~/.bashrc

我的shell是否配置为Bash?

要检查外壳是否配置为Bash,可以创建一个新会话,即创建一个新的Terminal窗口并运行:

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

如果打印出echo $0 ,则表明它正在使用Bash。

如何将我的shell配置为Bash?

如果-bash不打印echo $0,则需要更改外壳。要将其更改为Bash,请运行:

-bash

注意:您需要创建一个新会话以使此更改生效。


说明

  1. 项目特定的chsh -s /bin/bash 文件:

    .bashrc文件包含名为.bashrc的{​​{3}}。该函数的主体包含重写默认npm命令所必需的逻辑。

    • npm install|i --save语句中指定的条件,即读取的部分;

      if

      基本上读取if [[ $* == "install "* || $* == "i "* ]] && array_includes --save "$@"; then ... fi shell function来检查传递给$*函数的参数是否以其中一个开头; 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)时,我们将在其主体中执行以下任务:

      1. 通过如下行直接运行给定的true命令:

        npm install --save ...
      2. 通过以下内容检查command npm "$@" 命令是否全局存在:

        npx

        如果command -v npx >/dev/null 2>&1 || { log_warn_message npx return 1 } 命令(全局)不可用,我们警告用户npx命令无法运行,并且警告npx snowpack退出功能return,退出状态为{{ 1}}。

        注意::我在此检查中的逻辑假设您将在全局安装1。但是,如果要在项目中本地安装npx,则需要更改此逻辑。也许通过检查npm是否存在。或者,您可能会确信./node_modules/.bin/npx命令将始终存在,因此得出结论认为此检查是不必要的。

      3. 如果npx命令是全局存在的,那么我们运行伪的“ postinstall”命令,即

        npx
    • 如果不满足command npx snowpack 语句中指定的条件,即它们为if,则用户实际上正在运行不是false的任何其他npm命令。因此,在npm install --save <pkg_name>分支中,我们按原样运行命令:

      else
  2. 〜/ .bashrc文件:

    “ Bash参考手册”的special parameter部分中,command npm "$@" 变量的描述如下:

    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的{​​{3}}。

答案 1 :(得分:0)

我认为最好的选择是创建一个执行所需动作的新脚本。 package.json中的以下内容:

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

更正

您实际上可以在package.json中使用postinstall option。后安装将运行“安装软件包后”。看起来类似于以下内容:

{
  "scripts": {
    "postinstall" : "npx snowpack"
  }
}

答案 2 :(得分:0)

使用更新版本的Snowpack(> = 2),您可以运行snowpack dev,它将监视npm_modules文件夹中要构建的新模块。