Multiple commands in package.json - node.js

This command: "start": "node server/server.js" starts my server, but before running this I also want a command to run automatically:
'webpack'.
I want to build a script that can be run with
npm run someCommand - it should first run webpack in the terminal, followed by node server/server.js.
(I know how configure this with gulp, but I don't want to use it)

If I understood you correctly, you want firstly run webpack and after compile run nodejs. Maybe try this:
"start": "webpack && node server/server.js"

The following should work:
"start": "webpack && node server/server.js"
Though, for readability (and especially if you plan on adding additional tasks in the future), you may want to consider creating separate entries for each task and then calling each of those from start. Something like:
{
"init-assets": "webpack",
"init-server": "node server/server.js",
"start": "npm run init-assets && npm run init-server"
}

Better understand the && operator
In my case the && didn't work well because one of my commands sometimes exited with non zero exit code (error) and the && chaining operator works only if the previous command succeeds.
The main chaining operators behave like this:
&& runs the next command only if the first succeeds (AND)
|| runs the next command only if the first fails (OR)
So if you want the second command to run whatever the first has outputted the best way is to do something like (command1 && command2) || command 2
Others OS specific chaining operators
Other separators are different in a Unix (linux, macos) and windows environnement
; UNIX run the second command whatever the first has outputted
; WIN separate command arguments
& UNIX run first command in the background parallel to the second one
& WIN run the second command whatever the first has outputted
All chaining operators for windows here
and for unix here

You can also chain commands like this:
"scripts": {
"clean": "npm cache clean --force",
"clean:complete": "npm run clean && npm uninstall -g #angular/cli && rmdir /Q /S node_modules",
"clean:complete:install": "npm run clean:complete && npm i -g #angular/cli && npm i && npm install --save-dev #angular/cli#latest"
}

Also, along with the accepted answer and #pdoherty926's answer, in case you want to have run two command prompts, you can add "start" before each command:
{
"init-assets": "webpack",
"init-server": "node server/server.js",
"start": "start npm run init-assets && start npm run init-server"
}

Related

How to run few npm scripts in one-line shell command?

I have three scripts in package.json:
Watch server TypeScript
Nodemon
Webpack
"scripts": {
"watch-server": "tsc --watch --project ./server/tsconfig.json",
"watch-node": "nodemon --watch ./server/build/ --watch ./server/templates -e js,json,pug",
"watch-client": "webpack --config ./webpack/webpack.dev.conf.js --watch"
}
Everytime I start my computer and open VS Code I need to open three separate PowerShell terminals and type in those commands one-by-one. Is there any way to launch these three separate terminals with their own commands in one shell command? Maybe via tasks.json?
On linux or any bash terminal, you can use && to combine multiple commands, i
You can do as
npm run watch-server && npm run watch-node && npm run watch-client
A quick google search for powershell suggested using semicolon
so on powershell you can do something like below if using && does not work
npm run watch-server;npm run watch-node ; npm run watch-client
Also keep in mind, you can additionally add fourth command in your npm scripts in package.json where you can use one of these combined commands which works for you, like
start-all: npm run watch-server && npm run watch-node && npm run watch-client
and then run
npm run start-all

Webpack add watch mode without compiling

I have the following npm scripts:
"build:server:dev": "webpack --config ./webpack.server.dev.config.js --watch",
"build:client:dev": "webpack --config ./webpack.client.dev.config.js --watch",
"build:server:prod": "webpack --config ./webpack.server.prod.config.js",
"build:client:prod": "webpack --config ./webpack.client.prod.config.js",
"start:server:prod": "export NODE_ENV=production && node ./dist/server.*.js",
"start:iso:dev": "export NODE_ENV=development && npm run build:client:dev & npm run build:server:dev",
"start:iso:dev:win": "set NODE_ENV=development && concurrently --kill-others \"npm run build:client:dev\" \"npm run build:server:dev\"",
"start:iso:prod": "npm run build:client:prod && npm run build:server:prod && npm run start:server:prod"
The problem I'm facing is that the server compilation depends on the client compilation (I generate an html template where I inject the scripts with webpack on the client, and I use this template for server rendering in the server script).
In nearly all of the cases, the client finishes compiling before the server, but while running these scripts concurrently, there is no way to ensure that this will always be true.
When running webpack watch mode, it is not possible to run these scripts in sequence, as watch mode will block the second script from running.
The most obvious solution in my mind is to compile them without watch mode once, and then attach watch mode on the fly after the initial compilation.
I'm not sure how to achieve this though, and I would not like to compile them twice, just for the sake of attaching watch mode.
The second alternative I have in mind is to fiddle with webpack progress plugin, and somehow compile the server script after the client script has finished.
I dislike this solution, because I don't want to hard couple one script to another.
So is there a way to run client and server compilation sequentially from an npm script while using webpack --watch mode?
Maybe this will help you parallel-webpack although I didn't try it it has watch mode and would probably just require connecting your configs for both server and client side someway along this way:
// some script for running parallel builds
module.exports = [
require('./webpack.server.dev.config.js'),
require('./webpack.client.dev.config.js'),
];
then check running in watch mode
I found a nice solution using the npm package wait-on:
https://github.com/jeffbski/wait-on
The npm script I used (Unix & Windows):
"start:iso:dev": "export NODE_ENV=development && npm run clean:build && npm run build:client:dev & wait-on public/build/index-dev.html && npm run build:server:dev --inspect",
"start:iso:dev:win": "npm run clean:build:win && set NODE_ENV=development&& concurrently \"npm run build:client:dev\" \"wait-on public\\build\\index-dev.html && npm run build:server:dev\"",
This works like a charm.

package.json: what is the difference between & and &&?

Title pretty much says it all, but I'd also like to know if these commands work or behave differently depending upon the OS.
example1:
"scripts": {
"build": "babel -d serverbuild ./server",
"exe": "node ./serverbuild/index.js",
"start": "npm run build && npm run exe"
}
example2:
"scripts": {
"build": "babel -d serverbuild ./server",
"exe": "node ./serverbuild/index.js",
"start": "npm run build & npm run exe"
}
Given these examples portions of a package.json, what would be the difference between npm run start?
When using &&, the first command will run, and if it does not error, the second command will run. It's like a logical AND.
Using &, however, will run a command in the background. So in your second package.json, npm run build will start running in the background and then npm run exe will run as well regardless of what happens to the first command.

execute several "npm scripts" in order

I would like to command "electron-packer ." (it takes some time) and then "asar pack app app.asar"
Is it possible to do this?
Or should I simply wait for the first one and command the second?
You can queue commands like this.
npm run pack1 && npm run pack2
Or you can add another line that does the above and just run that alone.
"scripts": {
"pack": "npm run pack1 && npm run pack2"
}
Add this inside your "scripts" and you can just run npm run pack to run both of those commands.

npm start to run some scripts in silent mode

I have multiple scripts in package.json, most of them call some .js e.g. "copyResources" bellow. If I will run "npm run -s copyResources" in shell, it will execute silently. So far so good. But I would like to run "npm start" which will execute copyResource silently, example bellow, but this is not working (it's not silent). :(
Later I will have more scripts in "start" and I want to run some of them silently and some of them not. Thats the case why I can't just do npm start -s ...
"scripts": {
"copyResources": "echo 'Copy resources =>' && node ./bin/copyResources.js",
"start": "npm run -s copyResources"
}
Thank you very much!

Resources