First steps in deploying Node.js on Heroku yes image

First steps in deploying Node.js on Heroku

Recently, I used Heroku to deploy a website in the great wide open!
In this blogpost I want to tell about my first steps using Heroku, including the rookie mistakes I made: so you don’t have to make them.

Heroku in a nutshell:

“Heroku is a cloud platform that lets companies build, deliver, monitor and scale apps”
You can deploy your NodeJS application (or Rails or..) there with a simple git push.
The app will be build, deployed and can then be accessed via a link in the form of yourappname.herokuapp.com.

Beside the fact that it is easy to use, you also get a decent amount of online-time for free and it has a very good tutorial and how to get started which can be read on the website of Heroku.

Let’s start

First of all you need to make an account on Heroku and install the Heroku toolbelt. If you have done that you can login to Heroku in the commandline with

 heroku login 

Enter your credentials and you are logged in.
Then make a new project using.

 heroku create  

It will make you an app with an random appname. If you want to give the app your own name you can put the name of your application behind it. Like:

 heroku create amis-demo-app 

The application, make sure it uses git and has a package json. So:

git init
npm init

Name the app however you want. Don’t forget to .gitignore the node_modules.

Then make a little node server with express named server.js.
My first application is super easy: go to the page and it will send a “Hello world”.

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

Run it locally to see the Hello world! in the browser.

Now we want to put this on Heroku.
First we need a start script so Heroku knows what to run.
Add it to the script in the package.json:

 "scripts": {
    "start":"node server.js"
  }

Then add the engines. The what? The engines!
I locally use npm 3.10.3 and node v6.3.0. But Heroku doesn’t know that and has default versions of npm and Node. To make sure that Heroku uses the same version as we are using locally we set the engines in the package.json:

 "engines": {
        "node": "6.3.0",
        "npm": "3.10.3"
    }

Deploying the application

Now that we have made sure Heroku uses the same engines as we are we only need to link it to the remote Heroku git url which you can find in your dashboard.
Add the remote with git, add and commit everything and push to Heroku, since it is the first push, we need to set the upstream branch. We can use a normal git push heroku after this first one.
Don’t forget to .gitignore the node_modules as Heroku will do the npm install!

 git remote add heroku https://git.heroku.com/amis-demo-app.git //Use your own app url here!
git add -A
git commit -m "init"
git push --set-upstream heroku master 

Let ‘s go to the website and see how our “Hello world” is doing. Uh oh we see this:

application-error
This was my first real mistake. Luckily you can easily find out what happened by using heroku log in the console like this:

 heroku logs

It shows me this:
heroku-logs
With the most important message being:

 Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

With a bit of googling on that error I found out the problem:
Heroku dynamically assigns your my aplication to a port, so you can’t set the port to a fixed number, which I did!. Heroku adds the port to the environment, so we need to pull it from there. We change the app.listen to this:

app.listen(process.env.PORT || 3000, function () {
  console.log('Example app listening');
});

You can also do this using the Heroku procfile, check out there website for info on that one.

Now we commit and push and see what happens.
There it is!
Hello-word-her

Serving a frontend

The app is working. But I don’t want just a backend serving Hello world. I want a real html frontend, displaying a the AMIS logo!
Let’s make a public folder with an index.html and a images folder containing the image amislogo.jpg .

<html>
    <base href="/">
    <head></head>
    <body>
        <div>Hello</div>
        <img src="/images/amislogo.JPG"></img>
    </body>
</html>

We let the backend serve the frontend:

var express = require('express');
var path = require('path')
var app = express();

app.use(express.static(path.join(__dirname ,'/public')));

app.listen(process.env.PORT || 3000, function () {
  console.log('Example app listening');
});

If you run it locally you will now see a website with an AMIS image.

Add and commit all the files, push them to Heroku, wait for the build, open the app and…
no-image
My second mistake. What happened, where is the image? If you have a keen eye you saw the mistake I made which I can blame to my Windows sloppiness. Heroku is Linux and Linux is case sensitive. Locally I use Windows which doesn’t care so if I type JPG or JpG or jpg, it will show my image. Linux does care so be carefull! If we change the amislogo.JPG to amislogo.jpg in the index.html it will show the image, just as planned :).
yes-image
One last thing:
If you have bower dependencies on the frontend in the public folder instead of node_modules at the root, you can make Heroku automatically install those too by adding a postinstall script in the package json like this:

"scripts": {
    "start": "node server.js",
    "postinstall": "bower install"
  }

Code of this app can be found on my Github and of course you can view this beautifull app on amis-demo-app.herokuapp.com/
Resources:
https://devcenter.heroku.com/