Zarin
Zarin

Reputation: 112

NPM: make package.json work under both Unix (Mac OSX) and Windows

I've gotten some NPM package from a third party who is developing under Mac OSX. Their build can split into either development or production using "scripts" object in package.json. For example:

 "scripts": {
    "build": "NODE_ENV=dev node make.js --build",
    "build-prod": "NODE_ENV=prod node make.js --build",
  }

Under Unix, one can run either "npm run build" or "npm run build-prod" to build either directory (naturally, there are some conditional statements in make.js). Of course, it does not work under Windows - I had to change the commands similar to this:

 "scripts": {
    "build": "set NODE_ENV=dev&& node make.js --build",
    "build-prod": "set NODE_ENV=prod&& node make.js --build",
  }

(Please note that it was important not to put a space before the '&&' - otherwise the environment variable was created with an extra white space in it which ruined all those comparisons in make.js).

However, I would like to have some universal source tree which would work under either Unix or Windows without editing. Could you please give some ideas on how to conditionally split the build depending on the OS?

Upvotes: 7

Views: 4383

Answers (2)

Vasiliy
Vasiliy

Reputation: 998

The question is pretty old, but for these who faces the problem nowadays, npm starting from version >=5.1.0 supports setting shell for processing scripts. By default on Windows, npm internally uses cmd.exe for running scripts, even if npm command itself is typed in git-bash. After setting git-bash as shell, scripts that use bash syntax work normally on Windows:

npm config set script-shell "C:\\Program Files\\Git\\bin\\bash.exe"

Here one needs to substitute his correct path to git-bash executable.

Upvotes: 12

alandarev
alandarev

Reputation: 8635

I have been thinking for a while, but I doubt there is any aesthetic solution using these tools, to get the desired effect.

If you are able to influence the change in make.js, I would rather change this file to accept prod or dev as argument, example: node make.js --build=dev. With default value, to ensure backwards compatibility.

Using only npm and not modifying make.js, I could think of only running another JavaScript code, which would change environment variable, and then call make.js.

That will look something like:

"build": "node middleman.js"

Middleman.js file could then use child_process or another module to set variable and execute node make.js file.

If you do not want to create an extra file, you can then embed all the JavaScript inside the package.json using:

"build": "node -e 'my code'"

Be warned, that running "node -e 'process.env[\'NODE_ENV\']=\'dev\' && node make.js" will not work, as process.env sets variable in local process, not global (i.e. does not export to the system).


Not the direct solution, but for sake of best practices, make it work different.

Upvotes: 2

Related Questions