When working locally on a NodeJS project, nodemon is required in order to make the coding easier.
I frequently see the cases when it's installed as a dev-dependency only, so I wonder: what is the correct approach when it comes to deployment? Should we include it as a dev-dependency only, or should we include it into the server as well?
In this project I have, I see nodemon installed as regular dependency and then in the package.json configs:
"scripts": {
"start": "nodemon src/app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
But I am thinking to install it as a dev-dependency only and then to rework the config like:
"scripts": {
"start-prod": "node src/app.js",
"start-dev": "nodemon src/app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
So I wonder if this will be a correct approach?
I don't see a reason why on the server I would watch the file changes with nodemon, so I wonder if I got it right? In case sometimes it is needed, what are the possible cases when that will be required?
Short answer: You don't require nodemon in production.
According to nodemon on npm:
nodemon is a tool that helps develop node.js based applications by automatically restarting the node application when file changes in the directory are detected.
It is a tool to help in development, mainly restart the app server on file changes. You can add it to dev dependencies if you want to run nodemon via scripts. Otherwise you can install it globally.
npm install -g nodemon # or using yarn: yarn global add nodemon
And nodemon will be installed globally to your system path.
You can also install nodemon as a development dependency:
npm install --save-dev nodemon # or using yarn: yarn add nodemon -D
Edit:
If you want to keep your app alive even in case of any crash, you should consider using pm2.
PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime and to facilitate common system admin tasks.
Related
This question is much the same as Make angular app watch for libraries changes and update itself. But, that question was never successfully answered as applies to the use of multiple libraries. I also reviewed Angular library and live reload and surveyed the answers and links from both questions.
My app is using two libraries: lib-1 and lib-2. When those files are edited, they are ignored and the app does not recompile. To see changes, I have to restart the server which really slows things down.
My expectation is that the app should be recompile when library files are edited, just like when other app-internal files are edited.
This is an Angular project that I have inherited, and the original author is no longer available. I am using Angular v10 and npm 6.14.11
The initial npm scripts are:
"start:staging": "ng serve --configuration-staging --host 0.0.0.0 --port 8080 --disableHostCheck",
"build:lib-1": "ng build lib-1 && cpx projects/lib-1/src/lib/theme.scss dist/lib-1",
"build:lib-2": "ng build lib-2 && cpx projects/lib-2/src/lib/theme.scss dist/lib-2",
"build:libs": "npm run build:lib-1 && npm run build:lib-2",
With those, I first run npm run build:libs, then npm run start:staging. As mentioned, this does not "watch" my libraries for changes.
I reviewed the suggestions and the other SO questions (above), have ensured that the npm-run-all, wait-on and rimraf libraries are now installed.
I have written these new npm scripts:
"clean": "rimraf dist",
"start-app": "wait-on dist/lib-1/fesm2015 dist/lib-2/fesm2015 && start:staging --poll 2000",
"watch:lib-1": "npm run build:lib-1 --watch",
"watch:lib-2": "npm run build:lib-2 --watch",
"watch-libs": "npm-run-all --parallel watch:lib-1 watch:lib-2",
"watch-all": "npm-run-all clean --parallel watch-libs start-app"
And, I am using the pre-existing start:staging script, as written.
I run npm run watch-all.
The script runs and proceeds to the point of building the libraries in parallel (bad idea?), and then throws error: sh: start:staging: command not found.
I removed the --parallel switches and tried again, and got the same error.
The start:staging script is indeed in the scripts object, and I cannot figure out why it's not being found.
I'm hoping to get some sage advice on correcting my syntax so that the app will compile and watch my library files along with the other files that are inside the app's src folder.
After a lot of sleuthing, I came across Nikola Kolev's Angular 6: build — watch multiple dependent libraries in one shell post.
While I don't have it down to one npm script like Nikola was able to do, I am able to do it by running two scripts (there are 7 total scripts involved), and that's good enough for now. I'll work on condensing to one when I get more time.
First, be sure to have wait-on, rimraf and npm-run-all installed. We're also using cpx; but, that's not about getting the libraries to be "watched" -- just including to be overly thorough.
Here are all the scripts:
"clean": "rimraf dist",
"watch-lib:lib-1": "ng build lib-1 --watch",
"watch-lib:lib-2": "ng build lib-2 --watch",
"watch-libs": "npm-run-all clean --parallel watch-lib:*",
"copy-styles:lib-1": "cpx projects/lib-1/src/lib/theme.scss dist/lib-1",
"copy-styles:lib-2": "cpx projects/lib-2/src/lib/theme.scss dist/lib-2",
"start-staging": "ng serve --configuration-staging --host 0.0.0.0 --port 8080 --disableHostCheck",
"watch-staging": "npm-run-all copy-styles:* start:staging"
When I want to work on the libraries and have them be "watched", I run npm run watch-libs in one terminal. When that is finished, I run npm run watch:staging in a second terminal. Then, I'm able to launch the app in a browser, and any edits to any of the code, in libraries or in the app itself are caught, and the app recompiles as desired.
I have the below commands configured in npm scripts.Now, if i run the command "npm run dev" there is no response in command prompt. However, if the run the below command as "webpack -wd" in command prompt, then the command is working as expected. why, i am not able to run this command from npm scripts. I am using windows and have set the node path in environment variables as below
"scripts": {
"dev": "webpack -wd",
"test": "echo \"Error: no test specified\" && exit 1"
}
C:\Program Files\nodejs;C:\Program Files\nodejs\node_modules\npm\bin;C:\Users\[username]\AppData\Roaming\npm
If you want to run webpack via the command line, you either need to install webpack-cli globally with npm i -g webpack-cli or you need to use npx like npx webpack -wd. This will run webpack the same way npm scripts do.
The problem you are trying to circumvent is that webpack by default does not build the first time in watch mode, so you either need to change a file after starting webpack or run webpack without watch.
Note: npx is part of the NPM/Node.js bundle
brothers and sisters, I am trying to do this:
"scripts": {
"start": "node ./node_modules/.bin/http-server ./public",
"poststart": "webpack --watch"
}
It is not working. The idea being node runs the app (duh) and there's a webpack --watch instance rebuilding my code as it changes. What's the answer here?
One way to do it is like this:
you start webpack --watch in one terminal to watch the sources and rebuild when changes occur
you use nodemon (which is a npm package) in another terminal to watch for build (NOT source) changes and restart the app
Reference: https://nodemon.io/
When testing locally I was previously running:
"build-live": "nodemon --exec ./node_modules/.bin/ts-node -r dotenv/config -- ./index.ts"
I then figured my Procfile should be something like:
web: ./node_modules/.bin/ts-node -- ./index.ts
But it says module 'typescript' not found, even when it is in package.json. I read in a few places that ts-node is not the way to go to deploy to Heroku, so I am not sure what to do.
UPDATE: I think I am supposed to compile it, so I tried:
web: ./node_modules/.bin/tsc --module commonjs --allowJs --outDir build/ --sourceMap --target es6 index.ts && node build/index.js
This succeeds, however when actually running it, a bunch of the libs I'm using get "Cannot find module '...'".
Alternatively you can have the TypeScript compile as a postinstall hook and run node build/index.js as the only Procfile command:
Your package.json should contain a postinstall hint that gets executed after npm install and before the node process launches:
"scripts": {
"start": "node build/index.js",
"build": "tsc",
"postinstall": "npm run build"
}
You can then leave your Procfile as is:
web: npm start
This 'build on deploy' approach is documented by Heroku here.
The command you've given Heroku is to launch the web "process" by compiling index.ts and dependencies and starting node at index.js. Depending on how things are timed, index.js might or might not exist at the time node starts.
You need to already have your sources compiled by the time you want to start your app. For example, web should just be web: node index.js or similar.
Each build process is different, so you need to figure that out for your own setup. But, suppose you have a classical setup where you push to git and then Heroku picks up that change and updates the app with the new slug. You could just compile things locally and include index.js and any other build output in the repository, for it to be available in the slug for Heroku to use.
A better approach is to use a build server which has an integration with Heroku. After you do the build there, configure it to send the build results to Heroku. Travis has a straighforward setup like this. This way you don't need to include build outputs in your repository, which is considered an anti-pattern.
On a sidenode, try using a tsconfig.json to keep the tsc configuration. It will save you from having to write such long command lines all over the place.
Fabian said that we could do something like:
"scripts": {
"start": "node build/index.js",
"build": "tsc",
"postinstall": "npm run build"
}
As of me writing this, I tested this and can state: postinstall is not required since build script is ran by Heroku. If you want to do it without build script, then you can use heroku-postbuild which will run after dependencies are installed there you run tsc to compile.
My problem was about missing Typescript npm modules. The Typescript compiler tsc was not found when deployed the app to Heroku.
The Heroku deploy process (rightly) does not install development dependencies, in my case the Typescript module was part of devDependencies and thus the tsc command was not running on the Heroku platform.
Solution 1
Add typescript to dependencies: npm i typescript -s
Solution 2
Open Heroku console:
Select console type:
Run the command npm i typescript && npm run tsc
Install typescript as a dev dependency (cf. https://www.typescriptlang.org/download). Once built, your app does not need typescript anymore!
npm install -D typescript
Then in your package.json:
{
"main": "index.js", // <- file will be generated at build time with `tsc`
"scripts": {
"build": "tsc",
"start": "node ."
"start:dev": "ts-node index.ts" // idem, install ts-node as a dev dependency
}
}
The key point here is "build": "tsc".
Why?
Heroku does install all dependencies during build and remove the dev dependencies before the app is deployed (source here).
Node.js deployments will automatically execute an app’s build script during build (since March 11. 2019 source here)
In package.json
"scripts": {
"tsc": "./node_modules/typescript/bin/tsc",
"postinstall": "npm run tsc"
},
Works for me for Heroku deployment.
Installing typescript npm install -D typescript and writing tsc in the build script "build": "tsc", does not work for me. Also, try to run npm i typescript && npm run tsc in the Heroku console which also does not work.
In my case, I remove some dependencies from "devDependencies" to "dependencies", so it goes like this:
"dependencies": {
// The other dependencies goes here, I don't touch them.
// But all TS dependencies I remove to here.
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.3",
"ts-loader": "^8.0.18"
},
For someone who is coming from PHP background the process of killing node and starting it again after every code change, seems very tedious. Is there any flag when starting a script with node to automatically restart node when code change is saved?
A good option is Node-supervisor:
npm install supervisor -g
and after migrating to the root of your application use the following
supervisor app.js
You should look at something like nodemon.
Nodemon will watch the files in the directory in which nodemon was started, and if they change, it will automatically restart your node application.
Example:
nodemon ./server.js localhost 8080
or simply
nodemon server
forever module has a concept of multiple node.js servers, and can start, restart, stop and list currently running servers. It can also watch for changing files and restart node as needed.
Install it if you don't have it already:
npm install forever -g
After installing it, call the forever command: use the -w flag to watch file for changes:
forever -w ./my-script.js
In addition, you can watch directory and ignore patterns:
forever --watch --watchDirectory ./path/to/dir --watchIgnore *.log ./start/file
Various NPM packages are available to make this task easy.
For Development
nodemon: most popular and actively maintained
forever: second-most popular
node-dev: actively maintained (as of Oct 2020)
supervisor: no longer maintained
For Production (with extended functionality such as clustering, remote deploy etc.)
pm2: npm install -g pm2
Strong Loop Process Manager: npm install -g strongloop
Comparison between Forever, pm2 and StrongLoop can be found on StrongLoop's website.
You can also try nodemon
To Install Nodemon
npm install -g nodemon
To use Nodemon
Normally we start node program like:
node server.js
But here you have to do like:
nodemon server.js
node-dev
node-dev is great alternative to both nodemon and supervisor for developers who like to get growl (or libnotify) notifications on their desktop whenever the server restarts or when there is an error or change occur in file.
Installation:
npm install -g node-dev
Use node-dev, instead of node:
node-dev app.js
Notification on Changing file so server start automatically
console out put
Follow the steps:
npm install --save-dev nodemon
Add the following two lines to "script" section of package.json:
"start": "node ./bin/www",
"devstart": "nodemon ./bin/www"
as shown below:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node ./bin/www",
"devstart": "nodemon ./bin/www"
}
npm run devstart
https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website
I use runjs like:
runjs example.js
The package is called just run
npm install -g run
Nodejs supports watching mode since v18.11.0. To run it just pass --watch argument:
node --watch ./index.js
Note: this is an experimental feature.