7

我开始玩雪包。它采用与 Webpack 不同的方法,在安装后立即捆绑各个包。

“问题”是,当我安装一个包时,我必须先运行npm install --save my-package,然后我必须手动将其打包为npx snowpack. Snowpack 文档提到我可以包含一个脚本,该prepare脚本将snowpack在运行后执行所有操作,npm install但不适用于单个包,仅适用npm install于我的package.json. 据我所知,npm docs中提到的所有 npm 钩子都是这种情况。

有什么方法可以在我安装单个软件包时自动运行脚本?我能想到的唯一方法是覆盖安装脚本并添加一些东西。GitHub 或其他地方有这方面的例子吗?

更新:为了澄清起见,我想在npx snowpack每次安装新软件包时运行,--save但最好不要使用--save-dev或不使用--save. 对于任何包,这永远不会有所不同。这将特定于某个回购/项目,而不是我系统上的全局。

snowpack在简单地运行之后运行是不够的,npm install就像通过挂钩postinstallrelease. 此外,我想确保在我的项目上工作的开发人员可以npm install --save newdep像往常一样使用然后snowpack运行。我不想要求开发人员使用自定义命名脚本。

4

3 回答 3

10

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

生命周期钩子/脚本等postinstall仅在运行通用命令时调用,而不是在项目开发阶段npm install有人运行时调用。npm install --save <pkg_name>


解决方法:考虑通过在 shell 级别npm install --save覆盖命令来自定义复合命令的逻辑。npm

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

  • 开发您的项目的开发人员在运行复合命令时必须将其 shell 设置为Bash 。npm install --save
  • 为您的项目工作的开发人员将需要自定义他们的 Bash启动文件,也~/.bashrc可能是~/.bash_profile.
  • 项目目录,即您希望自定义逻辑对其生效的项目目录,必须包含自定义.bashrc文件。

重击解决方案:

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

注意:第 2 点和第 3 点(下文)是开发人员需要执行(一次)以自定义 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 启动文件,按照上述步骤 2 和 3。

  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
    

我的 shell 是否配置为 Bash?

要检查 shell 是否配置为 Bash,您可以创建一个新会话,即创建一个新的终端窗口并运行:

echo $0

如果它打印-bash,那么它正在使用 Bash。

如何将我的 shell 配置为 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存在来代替。或者,您可能确信npxcommand 将始终存在,因此得出结论认为此检查是不必要的。

      3. 如果该npx命令全局存在,我们将运行伪“postinstall”命令,即

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

      command npm "$@"
      
  2. ~/.bashrc 文件:

    “Bash 参考手册”的第5.2 节 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

于 2020-02-06T13:32:12.600 回答
2

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

于 2020-06-16T20:36:17.170 回答
1

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

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

更正

您实际上可以使用 package.json 中的postinstall 选项。postinstall 将在“安装包后”运行。这将类似于以下内容:

{
  "scripts": {
    "postinstall" : "npx snowpack"
  }
}
于 2020-02-04T20:02:57.723 回答