NodeJS(ES2015) + Heroku
First, âwhy Heroku?â The idea is actually to start with something simpler that everyone can use. Since I believe this platform is really more practical, it becomes perfect for our approach. In terms related to work itself, Heroku is a bit more expensive, a bit, but it compensates for its practicality. In the end, you have a cloud that serves you well, provides you with add-ons that are useful for your projects, and you can even get free SSL! Which is very good. In any case, Heroku is great both for simpler projects like what weâre going to do now, and for more elaborate projects, real projects. And with that, letâs go to another question: how to create a Node.js application with ES2015 that works perfectly with Heroku?! =]
I had researched several solutions for this, mainly because of some projects I received which were built in NodeJS and Angular, and currently (11/22/2016) if you look at Herokuâs documentation, the Getting Started on how to build a project with Node.js, it even has a repository and instructions on how to do it, but with a syntax that doesnât fully correspond to ES2015. And whether you like it or not, JS in ES6 is more readable, more practical and facilitates in various ways the development of your application, both by adopting let and its behavioral form in relation to scope, the new way of building functions, the organization of your class structures among other things that contribute to the maintenance of your code.
Anyway, letâs get to the code! Our project will have the following files:
.
âââ app.js
âââ package.json
âââ Procfile
âââ server.js
To start, letâs set up our package.json and to speed things up letâs type the following command: npm init -y And now letâs add the modules to package.json, which are basic to deploy this project and run npm install
"dependencies": {
"babel": "^6.5.2",
"babel-cli": "^6.14.0",
"babel-preset-es2015": "^6.13.2",
"express": "^4.14.0"
}
Once done, letâs move to our next file, app.js. With it weâll make some syntax changes. Until now, in older versions of Node.js you made module requests through requires, for example:
var express = require('express')
In ES2015, module calls are done through imports:
import express from 'express'
So letâs stick with import in our file to call the express module:
# app.js
# Module import
import express from 'express'
In the midst of this, another change is the form of composition. You used to create an app variable which received express and thus made use of the functions that derive from express, something similar to this:
var express = require('express')
var app = express()
The bad thing about this approach is that it had to be exported within a module.exports, actually a return of all middlewares or functions in a single block, for example passing app.set(âport) to be able to run the application in production or development. The code so far looked like this:
var express = require('express')
var app = express()
module.export = function(){
# here you would mainly put your middlewares
# and in the end just return the app loading everything
app.set('port', (process.env.PORT || 3000));
return app
}
Now with ES6 itâs even simpler:
import express from 'express'
const app = express()
app.set('port', (process.env.PORT || 3000))
export default app
Personally, I think this way the code is more readable, exactly because it is as simple as it is. But for a start, the simplicity of a well-done basic reflects a lot in the development of more elaborate applications.
Another significant change is the way to write request and response functions. You can write them using arrow functions. For example:
app.route(' / ').get((req, res) => res.end('Hello World'))
Itâs simpler to write functions like this than the next form found below. The reading is more fluid, especially for the versatility of being able in this case, to write the same function in one line. At least this gives you the feeling of understanding about what this function really does, which is strange if you try to concatenate the same function in one line in ES5.
app.route(' / ').get( function(req, res){
res.end('Hello World')
})
Everything in ES5 looks like this:
var express = require('express')
var app = express()
module.export = function(){
app.route(' / ').get( function(req, res){
res.end('Hello World')
})
app.set('port', (process.env.PORT || 3000));
return app
}
Now in ES6 our code looks like this:
import express from 'express'
const app = express()
app.route(' / ').get((req, res) => res.end('Hello World'))
app.set('port', (process.env.PORT || 3000))
export default app
What we see is the gain in readability and simplicity. Readability is the key word in all this, because in terms of maintainability, these small changes help considerably in large-scale projects. In fact, itâs still possible to separate and build an architecture with small modules to facilitate the organization of our application, because whether you like it or not, when you have a very large application, itâs not interesting to have, for example, route functions in a file that sets the basic modules for the application to function as a whole. ContinuingâŚ
The next file is server.js. Actually itâs the simplest since we understand the small modifications that give a nice syntactic sugar and facilitate the reading of our code. Well, first letâs import the app module that contains our configuration for a basic server and our main route.
import app from './app'
Then letâs add to our server the http request protocol, which is a native Node module that actually creates our server, and in the end our imports look like this:
import app from "./app"
import http from "http"
Once done, letâs actually create our server:
import app from "./app"
import http from "http"
http.createServer(app.get('port')).listen(port, ()=>{
console.log('server is running:'+ port)
})
Just to improve this all, letâs create a new constant for port:
import app from "./app"
import http from "http"
const port = app.get('port')
http.createServer(app).listen(port, ()=>{
console.log('server is running:'+ port)
})
Letâs go to one more file .babelrc. Itâs a file for loading plugins. In this case weâll have our plugin so we can write in ES2015:
/ * .babelrc */
{
"presets": ["es2015"]
}
Ok, weâre almost doneâŚalmost haha
Now, if you run the code, simply type node server, it will give the following error:
(function (exports, require, module, __filename, __dirname) { import app from "./app"
^^^^^^
SyntaxError: Unexpected token import
Why doesnât it work? Because Node doesnât have all the ES2015 features in its core, so weâll have to go back to our package.json and make a small modification to our scripts scope, and weâll write our start this way, using babel-node to run our server:
"scripts": {
"start": "./node_modules/.bin/babel-node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
}
Now if you type the npm start command, it will start the server locally and youâll see the Hello World from our application. So far our files look like this:
# app.js
import express from 'express';
const. app = express();
app.route('/') .get((req, res)=>res.end('Hello World'))
app.set('port', (process.env.PORT || 3000))
export default app;
# server.js
import app from "./app"
import http from "http"
const port = app.get('port')
http.createServer(app).listen(port, ()=>{
console.log('server is running:'+ port)
})
# package.json
{
"name": "node-heroku",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "./node_modules/.bin/babel-node server.js"
},
"dependencies": {
"babel": "^6.5.2",
"babel-cli": "^6.14.0",
"babel-preset-es2015": "^6.13.2",
"express": "^4.14.0"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Ready, now letâs go to the grand finale! The Deploy =] Letâs add the Procfile to our repository. Itâs just a file without extension called Procfile.
# Procfile
web: ./node modules/.bin/babel-node server.js
This file makes you run the server the same way you did in package.json, but this time it will initialize our application on Heroku. Itâs a very important file.
Now to upload all our files weâll have to initialize git, because Heroku also works through git. Actually, itâs the best way to upload your repository and letâs do the basics:
git init /* to initialize the git folder in the repository */
Once done, to not import everything, it doesnât hurt to add a simple .gitignore file to not upload node_modules to Heroku.
# .gitignore
/node_modules
And letâs commit everything.
git add .
git commit -m "initial commit"
Well, to perform the deploy you need to have an account on Heroku and need to download the Heroku Toolbelt client. After installing Heroku toolbelt and creating your account, youâll enter the repository where our code is and type the following command:
heroku login
It will ask for your Heroku account:
Enter your Heroku credentials.
Email: igor.p.r.vieira@gmail.com
Password (typing will be hidden):
Already properly authenticated, letâs go to our next and last step, create our application on Heroku. You can type the following command to create a URL automatically or you can create a URL for yourself manually:
# Automatic URL
heroku create
# Specific URL
heroku create meu-app-nodejs /*my application name*/
After creating our app on Heroku and since we already committed our repository, just run the command to deploy through git itself.
git push heroku master
Then youâll see the link to access your application.
In my case: https://my-app-nodejs.herokuapp.com/
And finally our Hello World! And thatâs it, it was long. The source code is below. Any questions, leave your comment. Thanks and see you later! =]
Source code: Github!