如果修改了package.json,则为npm install

Eug*_*gen 18 javascript node.js npm package.json

TL; DR:有没有办法npm install在运行任何npm脚本之前自动运行如果你package.json已经被修改了?

问题场景

您拉出或签出更新的分支package.json.你跑npm run my-script.my-script取决于新添加的包package.json.my-script失败.你想知道为什么.在翻过你的桌子之前,你npm install一定要确定.my-script运行成功.你不需要一张新桌子.

我知道构建/任务运行器工具就像gradle在运行任务之前确保您的依赖项是最新的.我一直是一个(次要的)痛点,npm没有做到这一点.我偶然发现了两个我不喜欢的解决方案.

非理想的解决方案:制造

package.json可以使用make并使用其集成的依赖关系跟踪,而不是依赖于运行命令中的npm脚本,并使用以下技巧:

# Smart install: Only executes if package.json's
# modification date is later than node_module's

node_modules: package.json
    npm install
    @rm -f node_modules/.modified
    @touch -m node_modules/.modified

install: node_modules 
Run Code Online (Sandbox Code Playgroud)

资料来源:https://mattandre.ws/2016/05/make-for-hipsters/

问题是你知道必须依赖于make运行脚本并失去npm脚本的某些优点,例如方便地引用其他脚本和并行运行脚本(npm-run-all).如果他们不知道make或运行有问题,也很难与他人合作(Windows).它是node/npm生态系统之外的一个古老工具,而且这个智能安装优势太高了.

非理想解决方案:Git钩子

另一种方法是添加一个post-mergegit钩子.

问题是该解决方案是存储库的本地解决方案,无法轻松共享.npm install只会在git merges上自动运行.当你package.json以任何其他方式改变时,你仍然需要记住跑步npm install.不可否认,这是实践中的一个小问题.尽管如此,npm install当您想要运行脚本时,永远不必考虑运行.

来源:https://davidwalsh.name/git-hook-npm-install-package-json-modified

理想解决方案

我想以package.json类似于以下的方式定义我:

{
  "scripts": {
    "pre-run": "npm-smart-install",
    "my-script": "…"
  },
  "dependencies": {
    "npm-smart-install": "1.0.0"
  }
}
Run Code Online (Sandbox Code Playgroud)

npm-smart-install是一个我希望存在的假设npm包.pre-run是一个假设的npm-scripts生命周期钩子.当我运行npm run my-script并且package.json自上次运行任何脚本以来一直被修改后,在运行npm install之前运行my-script.

重复一遍:npm install如果在package.json不依赖于npm生态系统之外的工具的情况下修改了你的任何npm脚本,有没有办法自动运行?

Che*_*vas 6

您可以创建一个自定义脚本来运行您的智能安装。

智能安装.sh 文件

#!/usr/bin/env bash

changedFiles="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"

checkForChangedFiles() {
    echo "$changedFiles" | grep --quiet "$1" && eval "$2"
}

packageJsonHasChanged() {
  echo "Changes to package.json detected, installing updates"
  npm i
}

checkForChangedFiles package.json packageJsonHasChanged
Run Code Online (Sandbox Code Playgroud)

然后,如果您有哈士奇,您可以将其添加到结帐后挂钩或您喜欢的任何挂钩中。如果您没有 husky,您也可以将其直接添加到脚本中,其本质上是做同样的事情。

.huskyrc 文件

{
  "hooks": {
    "post-checkout": "npm run smart-install"
  }
}
Run Code Online (Sandbox Code Playgroud)

package.json 文件

"scripts": {
  ...
  "smart-install": "bash ./bin/smart-install.sh",
}
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,创建一个 npm 脚本来运行都是一个好主意smart-install


nin*_*alt 5

好的,我已经完成了包裹。在这里。您可以完全按照您在理想场景中指定的方式使用它。只需npm install install-changed将其添加到自定义脚本中,就像pre-run在您的示例中一样。它应该弄清楚它是否需要,npm install如果需要就这样做。

 {
  "scripts": {
    "pre-run": "install-changed",
    "my-script": "…"
  },
Run Code Online (Sandbox Code Playgroud)

您也可以以编程方式执行此操作,但我认为您不需要这样做。

let installChanged = require('install-changed')

let isModified = installChanged.watchPackage() 
Run Code Online (Sandbox Code Playgroud)

上面的函数做完全相同的事情,此外它还返回一个布尔值,您可能会发现它很有用。

  • 有一个名为“package-changed”的 install-changed 分支,它基本上是相同的东西,但更灵活,允许您在 package.json deps/devDeps 更改时运行任何命令。然后我分叉了这个分支并将其命名为“lockfile-changed”,因为它只是创建“yarn.lock”内容的哈希值。这都是关于纱线的。我建议使用“package-changed”,除非你真的希望它基于yarn.lock+useyarn。如果你使用我的包,它可能有错误。我还没有测试过。 (2认同)