npm install if package.json was modified

Okay so I'm done with the package. Here it is. You can use it exactly the same way you specified in your ideal scenario. Just npm install install-changed and add it to a custom script, like pre-run in your example. It should figure out whether or not it needs to npm install and does so if it needs to.

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

You can also do this programatically but I don't think you're going to need this.

let installChanged = require('install-changed')

let isModified = installChanged.watchPackage() 

The function above does exactly the same thing, additonally it also returns a boolean value which you might find useful.


One easy solution is to use git diff and grep

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

this command first check difference between latest commit and last commit, from which it will list the files that are changed in latest.After that grep is used to find "package.json" in that list.If it finds that in the list it will run "npm install" either it won't.


Like other answers, but I think simpler because it's one line of shell script in package.json:

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

or, basically equivalent:

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

You'll have to either inline npm run install-if-needed or have a pre... script for each script that needs it -- I don't know any other way to have it run before multiple other scripts.

Explanation: install-if-needed checks the modification times on package.json and node_modules. If node_modules is newer, it does nothing; otherwise it runs npm install. The final touch node_modules is necessary because npm install may itself change the package.json modification time (if it is correcting whitespace in package.json for example).


You can create a custom script that will run your smart install.

smart-install.sh file

#!/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

Then if you have husky you can add that to the post-checkout hook or any hook you like. If you don't have husky, you can also add it directly to the scripts which essentially do the same thing.

.huskyrc file

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

package.json file

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

Either way it's a good idea to create a npm script to run smart-install