繁体   English   中英

npm install 如果 package.json 被修改

[英]npm install if package.json was modified

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

问题场景

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

我知道像gradle这样的构建/任务运行工具可以确保在运行任务之前你的依赖项是最新的。 我一直是npm不这样做的(次要)痛点。 我偶然发现了两个我不太喜欢的解决方案。

非理想解决方案:制作

无需依赖package.json中的 npm 脚本来运行您使用make的命令,并通过以下技巧利用其集成的依赖跟踪:

# 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),与其他人合作也更加困难。 它是 node/npm 生态系统之外的一个古老的工具,而且对于这种智能安装优势来说太昂贵了。

非理想解决方案:Git hook

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

问题是这个解决方案是存储库本地的,不能轻易共享。 npm install只会在 git 合并时自动运行。 当您以任何其他方式更改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自上次运行任何脚本以来已被修改时,请在运行my-script之前运行npm install

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

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

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

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

let installChanged = require('install-changed')

let isModified = installChanged.watchPackage() 

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

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

智能安装.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

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

.huskyrc 文件

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

包.json 文件

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

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

像其他答案一样,但我认为更简单,因为它是 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...脚本——我不知道有任何其他方法可以让它在多个其他脚本之前运行。

说明: install-if-needed检查package.jsonnode_modules的修改时间。 如果node_modules较新,它什么也不做; 否则它运行npm install 最后touch node_modules是必要的,因为npm install本身可能会更改 package.json 的修改时间(例如,如果它正在更正 package.json 中的空白)。

一种简单的解决方案是使用 git diff 和 grep

git diff --name-only HEAD HEAD~1 | grep package.json && npm install

此命令首先检查最新提交和最后一次提交之间的差异,从中列出最新更改的文件。之后使用 grep 在该列表中查找“package.json”。如果在列表中找到它,它将运行“npm install”或者它不会。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM