How to run Procfile with multiple commands on Heroku? - node.js

I'm trying to deploy the static website to Heroku and I struggle how to correctly setup the Procfile.
I have next command to run on the server:
npm install
gulp build (will make a build with /public folder)
http-server (will serve /public by default)
What I've tried:
web: npm install; gulp build; http-server
web: npm install & gulp build & http-server

Okay, so I've spent a bit of time on that and came up with the answer. By default, heroku is installing all packages from the package.json file, so npm install is no longer required. Then what was left - gulp build and http-server.
For that case, I've added "postinstall" : "gulp build" to my package.json and it left me with web: http-server.
Simplifying things have actually solved the problem. Not sure how useful that information might be to you, but it's worth to share.

You may also have been looking for && or a library like concurrently.
Regardless, and per the docs, use Procfile as nothing more than an entry point to your npm start script.
Use the npm scripts lifecycle as stated (npm-scripts).
Directly From The Documentation (heroku-build-process).
"scripts": {
"start": "node index.js",
"test": "mocha",
"postinstall": "bower install && grunt build"
}
Heroku has adopted the 'there's an app for everything' mantra, but for buildpacks. Whatever you're building, there's a buildpack for it.

You can run multiple command inside Procfile using sh -c command :
worker: sh -c 'firstCommand && secondCommand && etc...'
Notes : Procfile should be at the project root level.
For example :
worker: sh -c 'cd backend && yarn install && yarn build && yarn start-worker'
Or in your case (if u have Procfile at the same level as package.json) :
web: sh -c 'npm install && gulp build && npm run http-server'

Related

How to Serve a React App with Django on Elastic Beanstalk?

I used to have my app on Heroku and the way it worked there was that I had 2 buildpacks. One for NodeJS and one for Python. Heroku ran npm run build and then Django served the files from the build folder.
I use Code Pipeline on AWS to deploy a new version of my app every time there is a new push on my GitHub repository.
Since I couldn't figure out how to run npm run build in a python environment in EB, I had a workaround. I ran npm run build and pushed it to my repository (removed the build folder from .gitignore) and then Django served the files on EB.
However, this is not the best solution and I was wondering if anyone knows how to run npm run build the way Heroku can do it with their NodeJS buildpack for a python app on EB.
So I figured out one solution that worked for me.
Since I want to create the build version of my app on the server the way Heroku does it with the NodeJS buildpack, I had to create a command that installs node like this:
container_commands:
01_install_node:
command: "curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - && sudo yum install nodejs"
ignoreErrors: false
And then to create the build version of the react app on a Python Environment EB, I added the following command:
container_commands:
02_react:
command: "npm install && npm run build"
ignoreErrors: false
So of course, after the build version is created, you should collect static files, so here is how my working config file looked at the end:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: <project_name>/wsgi.py
aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: <project_name>.settings
aws:elasticbeanstalk:container:python:staticfiles:
/static/: staticfiles/
container_commands:
01_install_node:
command: "curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - && sudo yum install nodejs"
ignoreErrors: false
02_react:
command: "npm install && npm run build"
ignoreErrors: false
03_collectstatic:
command: "django-admin.py collectstatic --noinput"
Hope this helps anyone who encounters the same 🙂
I don't know exactly Python but I guess you can adapt for you case.
Elastic Beanstalk for Node.js platform use by default app.js, then server.js, and then npm start (in that order) to start your application.
You can change this behavior with configuration files. Below the steps to accomplish with Node.js:
Create the following file .ebextensions/<your-config-file-name>.config with the following content:
option_settings:
aws:elasticbeanstalk:container:nodejs:
NodeCommand: "npm run eb:prod"
Edit your package.json to create the eb:prod command. For instance:
"scripts": {
"start": "razzle start",
"build": "razzle build",
"test": "razzle test --env=jsdom",
"start:prod": "NODE_ENV=production node build/server.js",
"eb:prod": "npm run build && npm run start:prod"
}
You may faced permission denied errors during your build. To solve this problem you can create .npmrc file with the following content:
# Force npm to run node-gyp also as root
unsafe-perm=true
If you need more details, I wrote a blogpost about it: I deployed a server-side React app with AWS Elastic Beanstalk. Here’s what I learned.

How to run npm test after npm start in bash script

In my docker file, I want to run test script inside it after app is up in Docker dev version. Problem is when I created a bash script and add like that, test script is not working.
Here is my package json file:
"scripts": {
"build": "./node_modules/babel-cli/bin/babel.js src --out-dir lib --copy-files lib --plugins transform-react-jsx --presets es2015",
"bundle": "./node_modules/browserify/bin/cmd.js lib/client.js -o public/js/bundle.js",
"start": "npm run build && npm run bundle && node lib/server.js",
"test": "mocha ./src/*.test.js"
},
and here is bash script file
#!/bin/bash
npm start
npm run start
npm test
npm run test
Please let me know how to fix it, thanks much.
#!/bin/bash
npm run build
npm run bundle
forever start ./lib/server.js
npm test
I've found solution that I need to install forever or pm2 first.

Package.json for server and client

I want to install package.json for client side from my server side package.json as the server side is using node and client side is using angular 2
directory structure
server-app
--bin
--node_modules
--package.json
--client-app
--app
--node_modules
--package.json
now the problem is:
I have to run this command npm install from server app folder and also from server-app/client-app folder separately this will create deployment issues
what I want is to run only one time npm install from i.e server-app and it will automatically install the server-app package.json and client-side-app
package.json too.
Any help will be highly appreciated
I think what you need is a npm module called concurrently.
With concurrently installed in your root folder you can run multiple custom npm scripts.
For example: you can create 2 separate scripts that are installing the dependencies (client-install and server-install) and then create install-all-deps script that will run both scripts one after another and install all deps in both directories.
{
"scripts": {
"client-install" : "cd client && npm install",
"server-install" : "cd server && npm install",
"install-all-deps": "concurrently \"npm run server-install\" \"npm run client-install\""
}
}
Here is the npm module https://www.npmjs.com/package/concurrently. Quoting doc:
Run multiple commands concurrently. Like npm run watch-js & npm run
watch-less but better.
Hope this helps.
Structure your application in the following way,
app
--server-app
--client-app
--node_modules
--package.json
This way you can have single package.json file

gcloud deploy fails nodejs

I'm trying to deploy to google app engine. When I do so, the initial information all seems correct, the docker build is successful, but after docker it tries the following and fails:
Beginning teardown of remote build environment (this may take a few seconds).
Updating module [default].../Deleted [https://www.googleapis.com/compute/v1/projects/jamsesh-1219/zones/us-central1-f/instances/gae-builder-vm-20160213t114355].
Updating module [default]...failed.
ERROR: (gcloud.preview.app.deploy) Error Response: [13] Timed out when starting VMs. It's possible that the application code is unhealthy. (0/2 ready, 2 still deploying).
I know that I'm running es6 code transpiled to run on node 4.1.2 which is the version I'm told I can use here - I just have to run nvm install v4.1.2 which will switch me over, so I include that in my scripts. Here are my scripts in package.json:
"scripts": {
"test": "test",
"clean": "rm -rf lib",
"watch-js": "./node_modules/.bin/babel --plugins transform-es2015-classes src --presets react -d lib",
"dev-server": "./node_modules/.bin/webpack lib/client/entry.js",
"lint": "./node_modules/.bin/eslint ./src",
"server": "node lib/server/server",
"start-dev": "npm run lint && npm run build && npm run dev-server && npm run server",
"start": "nvm install v4.1.2 && node lib/server/server",
"styles": "./node_modules/.bin/lessc ./public/less/bundle.less ./public/css/bundle.css",
"build": "npm run clean && ./node_modules/.bin/babel --plugins transform-es2015-classes src --presets react -d lib && npm run styles"
},
and my docker file:
# Dockerfile extending the generic Node image with application files for a
# single application.
FROM gcr.io/google_appengine/nodejs
COPY . /app/
# You have to specify "--unsafe-perm" with npm install
# when running as root. Failing to do this can cause
# install to appear to succeed even if a preinstall
# script fails, and may have other adverse consequences
# as well.
# This command will also cat the npm-debug.log file after the
# build, if it exists.
RUN npm install --unsafe-perm || \
((if [ -f npm-debug.log ]; then \
cat npm-debug.log; \
fi) && false)
CMD npm start
So yeah, I've got no clue why the deployment failing. I could definitely benefit from some more thorough documentation on deploying node on GAE. It works on a test repo. Is there something else I need to be doing to run node on GAE with my babel6 transpiled code? Or should something be different in my scripts? In the Google Shell I can run locally fine once I switch to node v4.1.2

Restart node upon changing a file

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.

Resources