85

I have some custom testing script, which I can run with npm run test command, which executes some Node script for starting e2e/unit tests. But before it I must start webpack dev server with npm run dev (it's a some custom Node script too, details doesn't matter) in other terminal window. So, I want to omit npm run dev manually executing and move it to custom npm run test script, i.e. I want to execute webpack dev server programmatically in Node script. How can I execute npm run dev programmatically using Node script and stop it then?

"dev": "node node_modules/webpack-dev-server/bin/webpack-dev-server.js --host 0.0.0.0 --history-api-fallback --debug --inline --progress --config config/config.js"
starball
  • 20,030
  • 7
  • 43
  • 238
malcoauri
  • 11,904
  • 28
  • 82
  • 137
  • 1
    Why not create an `npm start` that runs the other two scripts? Like `"start": "npm run dev & npm run test"` – elclanrs Jun 25 '16 at 19:12
  • @elclanrs `npm run test` should not start before `npm run dev` – malcoauri Jun 25 '16 at 19:17
  • Why not run `webpack-dev-server` [programmatically](http://webpack.github.io/docs/webpack-dev-server.html#api)? – robertklep Jun 25 '16 at 19:57
  • @robertklep - it's a good suggestion, I'll try – malcoauri Jun 25 '16 at 19:58
  • @malcoauri if it doesn't work out, check out [this answer](http://stackoverflow.com/questions/15957529/can-i-install-a-npm-package-from-javascript-running-in-node-js/15957574#15957574), which explains how to run NPM programmatically. – robertklep Jun 25 '16 at 20:00
  • Does this answer your question? [Execute a command line binary with Node.js](https://stackoverflow.com/questions/20643470/execute-a-command-line-binary-with-node-js) – KyleMit Jan 03 '20 at 22:54

5 Answers5

88

You can use exec to run from script

import {series} from 'async';
const {exec} = require('child_process');

series([
 () => exec('npm run dev'),
 () => exec('npm run test')
]); 
element11
  • 4,218
  • 2
  • 16
  • 22
Foysal Osmany
  • 1,471
  • 14
  • 17
  • 4
    error: expected a function and UnhandledPromiseRejectionWarning: Unhandled promise rejection. – AtiqGauri Apr 28 '20 at 13:34
  • 2
    The UnhandledPromiseRejectionWarning error is because the series param expects an array of functions. So you can resolve this error by doing ```series([ () => exec('npm run dev'), () => exec('npm run test') ]); ``` – Chris Sep 05 '20 at 09:45
  • what I got working and what I think is the correct pattern is `(cb) => exec('npm run dev', cb)` – rubixibuc Sep 28 '21 at 03:55
  • Just FYI, this relies on an external package: https://www.npmjs.com/package/async – Max Strater Mar 17 '23 at 21:14
31

Here is a solution that should work reliably across all platforms. It's also very concise. Put this into build.js, then run node build.

const {execSync} = require('child_process')

execSync("npm run clean")
execSync("npm run minify")
execSync("npm run build_assets")

It will immediately abort on abnormal npm termination.

user1050755
  • 11,218
  • 4
  • 45
  • 56
28

Just install npm:

npm install npm

Then in your program:

npm.commands.run('dev', (err) => { ... });

See the source for more info. The npm.commands object is an unofficial API for npm. Note that using exec or spawn to execute npm is safer, since the API is unofficial.

zr0gravity7
  • 2,917
  • 1
  • 12
  • 33
mzedeler
  • 4,177
  • 4
  • 28
  • 41
  • 5
    Though there are advantages to @foysal-osmany's answer. See https://stackoverflow.com/questions/15957529/can-i-install-a-npm-package-from-javascript-running-in-node-js/19406194 – Xunnamius Sep 12 '18 at 15:40
  • Thats great! I didn't know you could use NPM as a module. Where is the JavaScript API documentation? – McShaman Feb 02 '19 at 02:17
  • I haven't been able to find any documentation. My answer is based on samples of code from various places. – mzedeler Feb 02 '19 at 08:21
  • 4
    Also note that I agree that using `exec` is safer. The reason that I used the `npm` module directly was in order to avoid spinning up a second node.js runtime. – mzedeler Feb 02 '19 at 08:24
  • 3
    @Xunnamius, no this is not the correct answer. Please refer to your own link. It is not safe to call npm as a module for several reasons. – Julian Knight Oct 12 '19 at 11:49
  • 1
    @JulianKnight You're right. Though I don't remember my usecase, I believe I used exec instead. Though I'm curious what you mean by "not safe" and "several reasons"? Do you just mean the size and unstable API? – Xunnamius Oct 12 '19 at 23:20
  • 2
    The unstable API and the fact that there have previously been issues between specific versions of npm/node.js – Julian Knight Oct 13 '19 at 11:10
  • 1
    As mentioned above - the API is internal and not safe to use unless you're ready to deal with unannounced breaking changes. I did it to avoid having two separate Node.js runtimes and it worked for me. – mzedeler Oct 19 '19 at 18:16
  • `npm.command` does not exist, exists `npm.commands` console.log(require('npm').command, require('npm').commands) – mikep Dec 30 '20 at 18:24
13

The npm documentation recommends using shelljs:

let shell = require("shelljs");

shell.exec("echo shell.exec works");
shell.exec("npm run dev");

See https://blog.npmjs.org/post/118810260230/building-a-simple-command-line-tool-with-npm.html

zr0gravity7
  • 2,917
  • 1
  • 12
  • 33
1

Use PM2, it is really usefull and easy...

npm install pm2
const pm2 = require('pm2');

pm2.start({
    script: 'npm -- run monitorTheWeather',
    autorestart : false 
  }, (err, apps) => {
    pm2.disconnect()
    if (err) { throw err }
  })
  • Using your code I get the following error: ` C:\givingway\gw-ts\t.js:11 throw err ^ [ Error: Script not found: C:\givingway\gw-ts\npm -- run test` – Ben Carp Nov 05 '20 at 14:37