npm install如果package.json被修改

时间:2018-09-23 13:46:36

标签: javascript node.js npm package.json

TL; DR:如果您的npm install被修改,有没有办法让package.json在运行任何npm脚本之前自动运行?

问题场景

您拉出或签出更新了package.json的分支。您运行npm run my-scriptmy-script取决于新添加到package.json的软件包。 my-script失败。你想知道为什么。为确保安全,在翻转办公桌之前,请运行npm installmy-script成功运行。您不需要新的办公桌。

我知道gradle之类的构建/任务运行器工具在运行任务之前请确保您的依赖项是最新的。 npm并没有为我带来一个(小)痛苦。我偶然发现了两个我不喜欢的解决方案。

非理想解决方案:make

使用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 

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

问题是您知道必须依靠make来运行脚本,并且失去npm脚本的某些优势,例如方便地引用其他脚本和并行运行脚本(npm-run-all)。如果其他人不了解make或在运行它时遇到问题(Windows),与他人合作也将变得更加困难。它是节点/ npm生态系统之外的一种古老工具,而且仅凭此智能安装优势就太昂贵了。

非理想解决方案:Git钩子

另一种方法是添加一个post-merge git钩子。

问题在于此解决方案是存储库本地的,无法轻松共享。 npm install仅在git merge上自动运行。当您以其他任何方式更改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"
  }
}

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

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

3 个答案:

答案 0 :(得分:2)

好的,我已经完成了包装。 Here是。您可以完全按照您在理想情况下指定的方式使用它。只需npm install install-changed并将其添加到自定义脚本中即可,例如您的示例中的pre-run。它应该确定是否需要npm install,并在需要时这样做。

 {
  "scripts": {
    "pre-run": "install-changed",
    "my-script": "…"
  },

您也可以通过编程方式执行此操作,但我认为您不需要此功能。

let installChanged = require('install-changed')

let isModified = installChanged.watchPackage() 

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

答案 1 :(得分:1)

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

smart-install.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

然后,如果您有沙哑的话,可以将其添加到结帐后挂钩或您喜欢的任何挂钩中。如果您没有沙哑的狗狗,也可以将其直接添加到实质上执行相同操作的脚本中。

.huskyrc文件

{
  "hooks": {
    "post-checkout": "npm run smart-install"
  }
}

package.json文件

"scripts": {
  ...
  "smart-install": "bash ./bin/smart-install.sh",
}

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

答案 2 :(得分:0)

与其他答案类似,但我认为更简单,因为它是package.json中的一行shell脚本:

{
    "scripts": {
        "install-if-needed": "[ package.json -nt node_modules ] && npm install && touch node_modules",
        "my-script": "npm run install-if-needed && ..."
    }
}

或基本上等同于

{
    "scripts": {
        "install-if-needed": "[ package.json -nt node_modules ] && npm install && touch node_modules",
        "premy-script": "npm run install-if-needed",
        "my-script": "..."
    }
}

对于每个需要它的脚本,您都必须内联npm run install-if-needed或有一个pre...脚本-我不知道有什么其他方法可以让它在多个其他脚本之前运行。 / p>

说明:install-if-needed检查package.jsonnode_modules的修改时间。如果node_modules是较新的,则不执行任何操作。否则,它将运行npm install。最后一个touch node_modules是必要的,因为npm install本身可能会更改package.json的修改时间(例如,如果它要更正package.json中的空白)。