Thursday, May 18, 2017

Running npm `postinstall` script after the original `npm install` finishes? (Maybe by using a Node trick?)

Leave a Comment

I'm trying to create an npm module that has a postinstall script that will modify the user's package.json and re-install packages. I'm almost there, but the problem I'm having is that the npm CLI runs my postinstall script too early.

Is there a way, maybe by using Node or system level trick, to wait for the whole npm install process to exit before my script runs? Like when npm calls my postinstall script, at that time I can register another script to run after npm install finishes?

What do I mean by "too early"? For example, after yarn install, the yarn.lock file will not accurately reflect the package.json if my script interferes with yarn install. However, if my script waits for yarn install to completely finish and then runs another yarn install, the yarn.lock file will be accurate and further yarn install commands will output "Already up-to-date".

2 Answers

Answers 1

postInstall as you have found out has very unusual way of execution and bugged in some versions of npm (all pre npm 3) , This was fixed in the later versions So first of all make sure your npm version is up to date; If it is you have 2 options that I can give you off the top of my head,

Option 1

This is the most simplest solution, use this script, it's pretty self explanatory it will install everything and to be on the safe side give the post install a once over. Not the most ideal solution but it should work without issues.

#!/bin/bash npm install npm run postinstall 

Option 2

Try moving your devDependencies to dependencies if possible, for some users this seem to fix the postInstall issue. But I don't recommend it devDependencies are there for a reason.

UPDATE

Ok, I get the issue now, but it should be covered with a slight variation to the option 1's script. Since your postinstall script can already handle the modification and re-installation.

#!/bin/bash npm install cd (<path to your modue> && npm run postinstall) 

Answers 2

Consider tempering directly with the package.json as bad practice, because Devs will no longer be in control of the packages they have installed, or even their project name.

Therefore, packages should instead request the Dev to change the package.json during installation and offer a method to enable Devs for a dry-run of the changes that will be made.

TLDR; make sure to give full consent to the Dev for any tempering with the package.json.

That's why I think alternative methods are better than using a postinstall script. The most minimal solution I have come up with:

myinstall.js

const exec = require('child_process').exec; exec('npm run install').on('exit', () => exec('npm run mypostinstall')); 

package.json

"scripts": {   "myinstall": "node myinstall.js",   "mypostinstall": "echo \"myPostinstall called\"" }, 

Set the mypostinstall script equal to the postinstall.

Note: in the example above there is no error handling, no text is displayed and there is no actual write to the package.json. It is pure for illustration on how to do execute code after npm install. The reason no text is being displayed is due calling exec, for which a new process is called with it's "personal" stdout. Alternatively use fork, more info can be found here at the node documentation.

I have attempted to call npm install instead of npm run myinstall by setting "install": "node myinstall.js". However now the exec('npm run install')will recursively call itself.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment