* * *

Summary:-

Learn how to deploy your node.js application to Heroku here : https://www.youtube.com/watch?v=P86N9FqNqso

If you get an application error after deploying your application, ensure the following have been done:-

  • In your package.json file, under the scripts field, add another script as follows : "start": "node index.js" (index.js is your entry point).
  • In your index.js(or app.js) file where you have started your server, make sure you have given the port number as process.env.PORT || 3000 instead of just a number. 
  • In your Procfile, ensure there are no unnecessary spaces. An ideal Procfile would look like "web:node index.js".

Free MySQL hosting website : https://www.freemysqlhosting.net/

Create an account on this website, verify your email and create a database. Wait for 5-10 mins for the database to go live and once you see the status to be "Live", you will receive a mail with the credentials to the database. Now open http://www.phpmyadmin.co/ and login using the credentials you received in your mail. You must be seeing a database. You cannot create more databases, you have to use the database they provided you with. Go to "SQL" part in phpMyAdmin and create tables as required. Then use the given credentials in your node.js application while connecting to the database.

 

Complete Tutorial:-

In the last article(http://aasf.in/aasf/postdetails.php?link=68), I had described how to use express-ejs-layouts and ejs to render dynamic data. In this article, we will build and deploy a complete end to end HTML + Node.js + MySQL application using EJS but without using express-ejs-layouts.

 

First things first, create a folder named "heroku-node-app", navigate to this folder and run "npm init" inside this folder". 

Run 

npm i express body-parser mysql ejs

in the same folder to install express, body-parser, mysql and ejs, the only four dependencies we'll be needing.

Go to package.json file, and under the scripts property, add another script as folows :- "start": "node index.js". Your package.json should look something like this:-

https://drive.google.com/open?id=1apNbEZMGqI1_TG1YfFkAWkv0J-9yhOpy

 

Now create a file "index.js" and paste the following code in it:-

const express = require("express");

const bodyParser = require("body-parser");

 

const app = express();

 

app.use(bodyParser.json());

app.use(bodyParser.urlencoded({ extended: false }));

 

app.get("*", (req, res) => {

res.send("Working!");

});

 

const PORT = process.env.PORT || 3000;

 

app.listen(PORT, console.log(`Server started on port ${PORT}`));

Now in the terminal, run

npm start 

npm can also be used to execute scripts. "node index.js" is now your start script. So whenever you run "npm start", npm will automatically execute "node index.js".

You should be able to see "Server started on port 3000" in your terminal and if you open localhost:3000, you should be seeing "Working!".

Observe how the PORT has been declared as process.env.PORT || 3000 instead of simply writing 3000. There is something called as an environment variable, we won't get into environment variables now. Just know that when we will be deploying our application on Heroku, Heroku provides an environment variable called PORT and that will be used as a port number instead of 3000. If you wish to explore more about environment variables, here you go:- https://www.twilio.com/blog/2017/08/working-with-environment-variables-in-node-js.html

 

Now let's set up a few basic routes. This is what we're going to build:- A HTML form which takes in name, email and phone number of user. This form will be displayed when the website is opened. Submitting the form should trigger a POST request to /submit endpoint, which will add this data into the database. /users endpoint will display all the users we have added through the form.

Before we build the endpoints, we need some HTML. In the heroku-node-app folder, create a new folder called "views". In this folder, create a file called "form.ejs". Mind the extension, it is ".ejs" and not ".html". Paste the following code into form.ejs:-

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<title>Form</title>

</head>

<body>

<form action="/submit" method="POST">

<label>

Name :

<input type="text" placeholder="Name" name="name" />

</label>

<label>

Email :

<input type="email" placeholder="Email" name="email" />

</label>

<label>

Phone :

<input type="tel" placeholder="Phone" name="phone" />

</label>

<button type="submit">Submit</button>

</form>

</body>

</html>

Sorry for the badly indented code, this editor automatically removes indentation. If you're on VS Code, pressing ctrl+shift+i will auto format the code(thank me later, if you didn't already know this). But this auto formatting will work only if you have no errors in your code.

 

Observe the <form> tag, the action="/submit" attribute specifies the route that has to be triggered when the form is submitted and method="POST" attribute signifies the HTTP Method which has to be used for the request. So when the form is submitted, a POST request is sent to localhost:3000/submit endpoint. Make sure you give the "name" attribute to the input tags in your form, these will be the names by which you can access the values of these fields in req.body later on. So req.body.email will contain the form value of the email field.

 

Create a file "users.ejs" within the views folder and paste the following code:-

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<title>Users</title>

</head>

<body>

<ul>

<%for(let i=0; i<users.length; ++i) {%>

<li>User <%=i+1%> :

<ul>

<li>NAME : <%=users[i].name%></li>

<li>Email : <%=users[i].email%></li>

<li>Phone : <%=users[i].phone%></li>

</ul>

</li>

<%}%>

<a href="http://localhost:3000/about">About Page</a>

</ul>

</body>

</html>

users here is an array which I will be passing to this file while rendering it. If you're confused about this, please read the previous article, the link to which is mentioned above. I'm simply iterating over the users array and printing the Name, Email and Phone as an unordered list.

I have created an about page link just to show how internal routing can be done.

Now create a file named "about.ejs" in the views folder and paste the following code in it:-

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<title>About</title>

</head>

<body>

<h1>About Page</h1>

</body>

</html>

Now before we build our routes, let's host a MySQL database online so we can use it in our application to store the user details.

Go to https://www.freemysqlhosting.net/, create a new account and verify your email. After logging in with your newly set password, you should see a dashboard similar to this:-

https://drive.google.com/open?id=1mrcmPITcc0Ab73DAuT8C65pbeyojq_jh

 

Set the server location to Asia Pacific. Click on "Start new database" and wait for about 5-10 mins for the "Status" to turn "Live". Keep reloading to check if the database is live. Once live, you will receive a mail with your database details. Wait for another 5 mins to receive this mail. Be patient with them, they are providing free hosting services after all.

Now go to http://www.phpmyadmin.co/. In the login form, give the details for server, username and password as sent in your mail and login. Go to the "Databases" tab and you should see something like this:-

https://drive.google.com/open?id=1mQYVdE7YRen-ddIBwYoUrURyjtCdFmId

Select the database with the "sql" prefix followed by a number. Now go to the "SQL" tab and type in the following query:- 

CREATE TABLE users(id int AUTO_INCREMENT PRIMARY KEY, name varchar(255), email varchar(255), phone char(10));

Click on "Go" or press ctrl+enter to execute the query. The query should execute successfully and an empty table must be created.

We're all set to integrate this database with our application.

 

In the heroku-node-app folder, create a file called "db.js" and add the following code to it:-

const mysql = require("mysql");

 

const mySqlConnection = mysql.createConnection({

host: "sql12.freemysqlhosting.net", //Or whatever you received in your mail

user: "<THE USERNAME YOU RECEIVED IN MAIL>",

password: "<THE PASSWORD YOU RECEIVED IN MAIL>",

database: "<THE NAME YOU RECEIVED IN MAIL(This is the same as your username)>"

});

 

mySqlConnection.connect(err => {

if (err) console.log(err);

else console.log("Database Connected!");

});

 

module.exports = mySqlConnection;

We're simply creating a mySQL connection here, as mentioned in the 2nd article in the Node.js series(http://aasf.in/aasf/postdetails.php?link=67).

 

Now let's build some routes. Update your index.js with the following code:-

const express = require("express");

const bodyParser = require("body-parser");

const mySqlConnection = require("./db");

 

const app = express();

 

app.use(bodyParser.json());

app.use(bodyParser.urlencoded({ extended: false }));

app.use(express.static("public"));

app.set("view engine", "ejs");

 

app.get("/", (req, res) => {

res.render("form");

});

 

app.get("/about", (req, res) => res.render("about"));

 

app.get("/users", (req, res) => {

let sql = `SELECT * FROM users`;

mySqlConnection.query(sql, [], (err, rows) => {

if (err) res.status(500).send("Some error occurred");

else res.render("users", { users: rows });

});

});

 

app.post("/submit", (req, res) => {

const { name, email, phone } = req.body;

let sql = `INSERT INTO users (name, email, phone) VALUES ?`;

const values = [[name, email, phone]];

mySqlConnection.query(sql, [values], (err, rows) => {

if (err) res.status(500).send("Some error occurred");

else res.redirect("users");

});

});

 

const PORT = process.env.PORT || 3000;

 

app.listen(PORT, console.log(`Server started on port ${PORT}`));

If you're confused about what res.render is or how we're sending values to an ejs file, please read the previous article(http://aasf.in/aasf/postdetails.php?link=68)

app.use(express.static("public")) signifies that all your static files(css, images etc.) are present in a folder called public. So if you do have any such files(you obviously should), put them into the public folder, and you can import them using "./<filename>" wherever you need. For example, <img src="./myPic.png" /> supposing I have a picture named myPic.png in the public folder. It is a good design practice to separate our different kinds of files, so though not necessary, inside your public folder, create different folders for CSS and Images and other files, and use them as "./css/<css file name>" or "./images/myPic.png" instead.

app.set("view engine", "ejs") mentions that we're using ejs as our templating engine. So whenever we call res.render with any name, for example "users", the app is going to look into the views folder and look for a file name "users.ejs" and render it.

Here we have 4 routes. A GET request to "/" endpoint should render our form page. A GET request to "/about" endpoint should render the About page. Go back to users.ejs file to see how the href is given for about page, so basically when that link is clicked, a GET request is sent to the "/about" endpoint and hence the about page is rendered.

A GET request to the "/users" endpoint will fetch all the users from the users table and render the user.ejs file and that file will be supplied with the rows fetched from the database and the name of this array which will be sent to the ejs file is users, as mentioned in the object.

A POST request to submit will extract name, email, phone from req.body first(This is called object destructuring, i.e., extracting individual fields from an object), then a query will sent to the database to insert these values into the users table. After inserting, you will be redirected to the users page. res.redirect is a function which gives you the power to send a GET request to any route. So when you say "res.redirect("users")", a GET request will be sent to /users endpoint, and hence the users will be fetched and the users page will be rendered.

Save this file and run "npm start" in your terminal. You should see "Server started on port 3000" and also "Database Connected" if you have done everything properly. You should see a form like this when you open localhost:3000 :-

https://drive.google.com/open?id=1yn0NSsk8NU9towK_U1x2120j-fro0W5C

Fill the form details and ensure that the phone number is only of 10 digits because we had the restriction of 10 characters while creating the table. Submit the form and you should see the users page like this:-

https://drive.google.com/open?id=129-Xqv0IaPgwRtXp3tGuC54VVJ-V5HQu

Clicking on the "About Page" link should take you to the about page.

 

Now all of this has been running on our local server(except for the database of course). Let's deploy this application to Heroku. Now you can either follow the article ahead or watch this video to learn how to deploy a node app onto heroku:- https://www.youtube.com/watch?v=P86N9FqNqso. I have mentioned a few other details in the article, so I would suggest you to go ahead with the article and use the video as a reference later on.

 

In the heroku-node-app folder, create a file named "Procfile". Yup, just "Procfile", no extension. And paste the following content into that file:-

web:node index.js

I had an error when I used extra spaces between web and : and node, so avoid doing that. 

Save the file and close it.

Go to https://www.heroku.com/, create an account if you do not have one and verify your email. 

Now we have to install Heroku Command Line Tools. Go here:- https://devcenter.heroku.com/articles/heroku-cli and follow the instructions to install the tools for your OS. I would highly recommend you use Ubuntu.

After you have installed them, go to your terminal and run "heroku --version" to check if they have been properly installed. If you can see the version, that means you have done it right.

Now in your terminal, type "heroku login" and follow the instructions to login. You will probably be asked to enter your heroku credentials, or will be asked to press any key and will be redirected to a webpage where you have to login.

Now run "heroku local web" on your terminal. Heroku will now automatically start your server on localhost:5000. Go ahead and check if this works on localhost:5000. Now why did the app get deployed on port 5000 and not 3000? That's because Heroku provided the application with an environment variable PORT with the value 5000 and hence this was used instead of 3000, which we provided.

Before deploying our application to the web, we will have to initialise a git repository for our project. So in the heroku-node-app folder, run "git init" and this should initialise the git repository. Make sure you have git installed in your system before doing so. 

Firstly, in the heroku-node-app folder, create a file named ".gitignore". Yes, there is a "dot" before the file name, it's not a typo.

Add the following line to the .gitignore file:-

node_modules

The .gitignore file mentions all the files that have to be ignored by git. These files won't be tracked by git and they won't be pushed to the github repository if we have a remote connection.

Why do we need this? Node Modules is a very very heavy folder with a lot of files and it basically just contains the dependencies needed for the project. If someone needs those dependencies, they can just download them at their end, right? All they have to know is the list of dependencies needed. How do they get to know that? From the package.json file, which contains a list of all dependencies your project needs. Now will that other person copy paste every dependency into an npm install command? That would be tedious, right? Let's see what we can do.

Go to your project, and delete the node_modules folder(don't worry, we'll get it back). Now in your terminal, run "npm install". Yup, just "npm install" without any dependency name. You should see a new node_modules folder now, if you don't see this in your text editor, close it and reopen it. So basically running "npm install" will install all the dependencies mentioned in the package.json file automatically. 

So write "node_modules" to the .gitignore file so that git doesn't track that folder. You wouldn't be facing a problem by pushing this node_modules folder to github at this moment because of the less number of dependencies you might be using, but imagine a large scale applications with hundreds of dependencies. The node_modules folder would be very very large in size and it is not recommended, nor is it allowed to store very huge files, folders on github.

 

Okay so enough of .gitignore. Now run "git add ." and " git commit -m "complete application" " in your terminal.

Now run 

heroku create

in the terminal and after you get a "Done" message, open https://dashboard.heroku.com/apps, login if you haven't and you should see your app being listed there. Heroku gives you random names for your application, don't worry about that. After you had run this command, you should be seeing a github repository link as an output, It would be something similar to this:-

https://drive.google.com/open?id=1ZUkZQDh-jyFSYe01pK5msOyUE6f8SG77

Copy that github repository link and run 

Your link will obviously be different from mine, paste your link in the above command. Master signifies that we'll be pushing it to the master branch of that repository. Do not copy paste this command, type it out in your terminal.

This command will produce a long output, at the end of which will be a line which says something similar to :-

remote:        https://lit-reef-94485.herokuapp.com/ deployed to Heroku

 

Open this link(the link you have in your terminal, not mine) in your browser, and I really really hope you can see your website deployed on the web. If you open the above mentioned link, you can see the website that I just deployed.

 

If you have to make any changes to your project, make those changes, add and commit those changes and run the exact same "git push" command as you have done above. The website will be automatically deployed by Heroku with your changes.

 

As I said, heroku by default gives you random names for your application, if you wish to rename it, you may do so using the following command in your project folder:-

heroku apps:rename <newname>

Replace <newname> with a name that you would like your app to have. I would suggest you to go with <YourName>-<ProjectName> because common names are usually taken by others. Make sure there are no spaces in your application's new name, and different words can be separated using "-". Once you rename the app, you will get a new git repository link, you now have to push your code to that link instead of the previous one.

 

So congratulations, you have successfully build an end-to-end HTML + Node.js + MySQL project to the web. 

 

Cheers.

For any queries, you can ping me on LinkedIn :- https://www.linkedin.com/in/guna-shekar-proddaturi/