How-to-create-a-Node.JS-application

Probably this isn’t the first post you read about “How to begin an application with Node.JS”. That are a lot of those around. Most using express.js, for example. In this one, We’ll show what is possible using only Node.JS native library.

If you didn’t install Node.JS yet, just click here aqui.

I’m going to assume that you know something about JavaScript and understand how callbacks work. If you don’t have any idea how callbacks work, read this.

This is NOT for someone who is new in the world of development. If this is your case, this post is for you.

Another tip: Follow this post creating the application as an example. Also, read the content of the post.

Where to begin?

$ npm init

This is the first command that you will execute in a blank application.

In our example, let’s name it fakemytemplate, version 1.0.0, without any description. On the rest, you can click enter.

package.json probably is the most important archive in a Node.JS application. In it, we specified the name, version, authors and not less important, thedependencies.

Is common to have a lot of dependencies in a Node.JS application. It’s easy to reuse open-sources codes that you find at GitHub or at npm. This makes Node.JS to be a fast developing environment (there are MANY libs).

That’s why is important to choose carefully a lib. Your code dependent on it. Even if you have abstraction layers, at the end, you’ll still be using this lib. Be careful when choosing.

A quick recommendation: choose a known lib.The ones which are constantly updated and with good documentation. For your own good, please don’t choose one that have not been updated for years.

In this tutorial, we will only use the: Faker.js lib. It’s a lib used to generate false data. highly recommend for you to take a look at the documentation, just to understand what it really do.

Installing a dependency:

$ npm install --save faker.js

Every dependency installed comes from a site called npm (Node Package Manager). It comes with Node.JS installation kit.

When we run the command, it will search the lib in npm record (in this case, faker.js).

Hint: Run the command with the option –save. It will include automatically the dependency in your package.json.

We noticed that a new folder appeared in our project, node_modules. Our dependencies will be installed there.

Package.json

As I said before, it’s the most important file in our application. Let’s take a look.

{
"name": "fakemytemplate",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"faker": "^3.1.0"
}
}

Observe that it included the faker like as a dependency in a recent update at npm. To see how versioning works at npm, recommend you to read the documentation.

With the dependencies correct listed at the package.json, it’s time to run, again the command npm install. It will reconstruct node_modules folder and install dependencies again. That’s why we should keep package.json updated. This will make everybody’s life easier during the project. The only thing they need to do is execute the npm install.

If you are working with git or another versioning tool, you can ignore node_modules folder.

Since we talked to package.json that our main file is the index.ks, let’s created it one:

const faker = require('faker');

const randomName = faker.name.findName();
console.log(randomName);

And run this:

$ node index.js

Magnolia Glover

We only imported the lib faker using the instruction require(‘faker’), call the aker.name.findName() method, so it can generate a random name and show it atconsole.log.

If you are not used with ES6 (newest JavaScript version), the const is like the var. But with a difference. If you define a variable using const, it can’t be modified.

For example:

const faker = require('faker');

const randomName = faker.name.findName();
randomName = faker.name.lastName();

console.log(randomName);

This code will result in an error because we can’t define the message’s variable. randomName.

Let’s change a little the package.json and include a script named start.

{
"name": "fakemytemplate",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"faker": "^3.1.0"
}
}

Now, when dispatch a npm start, the node index.js command will be executed:

npm start

> fakemytemplate@1.0.0 start /home/ubuntu/fakemytemplate
> node index.js

Jamar Klein

Let’s now create a server that, when receiving a request, will send a random name.

For this we will use thehttp lib, native too.

const faker = require('faker');
const http = require('http');

const server = http.createServer();

server.on('request', function (request, response) {
const randomName = faker.name.findName();

response.write('Your random name: ' + randomName);
response.end();
});

server.listen(3000);
console.log('Server is running.');

Nice! I can imagine you looking this code and freaking out.

Relax!

> const http = require('http');

The same way we imported faker, we are doing now with http Node.JS module.

> const server = http.createServer();

We call a method namedhttp.createServer from httpmodule. This will return a new instance from class http.Server.

Deeper, the http.Server class inherits one EventEmitter, that, we can say, is the Node.Js’ core but talking about this will make this “How to begin…” much more complex. So, for now, let’s skip this part. But if you have interest, We will have another post talking about EventEmiiter in the following weeks.

Everyone that already used JavaScript at the web browsers will recall Dom events (onclick, onload, etc.).

server.on('request', function (request, response) {
const randomName = faker.name.findName();

response.write('Your random name: ' + randomName);
response.end();
});

Understanding the .on() method of every class inherits from EventEmitter:

Our server’s object, upon receiving a request, will send and event called request. So, we use  .on() to put a listener for the event, through a callback function.

If you don’t know about callback, I recommend you research a little before continuing. .

The callback function will receive two arguments form request event. The first is an object with informations from a client request and the second one is an object used to respond to to the client.

So, our callback to the event request will create a random name.

> const randomName = faker.name.findName();

Write on body’s answer the generated name.

> response.write(randomName);

And finish the answer.

> response.end();

The next step is to do our server listen to one port. In this case, port 3000.

server.listen(3000);
console.log('Server is running.');

And execute our index.js.

$ npm start

> fakemytemplate@1.0.0 start /home/ubuntu/fakemytemplate
> node index.js

Server is running.

It’s important to pay attention that the code that Node.JS is executing is not “automatically updated”. You have to restart your application every time that you chance the code. Node.JS, differently from others runtimes, don’t open one thread or process for each request. Node.JS’ applications are single thread. You code remain static and requests are treated asynchronously. In parallel. But, still, been single thread will not have two blocks of code been execute simultaneously. We can say that Node.JS is not recommended to execute a code that uses a lot of processors (CPU bind) resources but is great for codes with a lot of in/out (I/O bind) operations.

You may have notice that our process was not finished. Yes, our server is still running.

Let’s test a request forlocalhost:3000.

You can open on your browser but we will use the curl.

$ curl localhost:3000

Your random name: Ernesto Brakus

It’s time to put more stuff in our application.

Let’s use the powerful faker.fake method that receives a template and returns a text according to the template that was used.

faker.fake("{{name.lastName}}, {{name.firstName}} {{name.suffix}}");

// outputs: "Marks, Dean Sr."

Using the method faker.fake for when our server receives one request it will be a parameter template and send to the client the result.

Something like this:

$ curl -G "localhost:3000" --data-urlencode "template=Hello {{name.firstName}}"

Hello Shanelle

Let’s take a look on how we receive the parameter template. For this let’s inspect the parameter request.url.

const faker = require('faker');
const http = require('http');

const server = http.createServer();

server.on('request', function (request, response) {
console.log('request.url:', request.url);
const randomName = faker.name.findName();

response.write('Your random name: ' + randomName);
response.end();
});

server.listen(3000);
console.log('Server is running.');

That console.log(‘request.url:’, request.url) i will show something like this:

request.url: /?template=Hello%20%7B%7Bname.firstName%7D%7D

It’s getting confused, right? Let’s parse the url using the url module, also native.

const faker = require('faker');
const http = require('http');
const url = require('url');

const server = http.createServer();

server.on('request', function (request, response) {
const parsedUrl = url.parse(request.url);
console.log('parsedUrl:', parsedUrl);

const randomName = faker.name.findName();

response.write('Your random name: ' + randomName);
response.end();
});

server.listen(3000);
console.log(‘Server is running.’);

console.log(‘parsedUrl:’, parsedUrl) will show this:

parsedUrl: Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?template=Hello%20%7B%7Bname.firstName%7D%7D',
query: 'template=Hello%20%7B%7Bname.firstName%7D%7D',
pathname: '/',
path: '/?template=Hello%20%7B%7Bname.firstName%7D%7D',
href: '/?template=Hello%20%7B%7Bname.firstName%7D%7D'
}

Basically, the module URL’s responsibility is to treat URLs.

Let’s use the parameter query that contains the part of the querystring from our URL that was parsed.

Using the module querystring for parse our query string and remove undesirable parameters.

const faker = require('faker');
const http = require('http');
const url = require('url');
const querystring = require('querystring');

const server = http.createServer();

server.on('request', function (request, response) {
const parsedUrl = url.parse(request.url);
const parameters = querystring.parse(parsedUrl.query);

console.log('parameters:', parameters);

const randomName = faker.name.findName();

response.write('Your random name: ' + randomName);
response.end();
});

server.listen(3000);
console.log('Server is running.');

console.log(‘parameters:’, parameters) will show this:

parameters: { template: 'Hello {{name.firstName}}' }

Now that we have the parameters that we want, lets’ pass this to faker.fake() parameter and send the result back to the client.

const faker = require('faker');
const http = require('http');
const url = require('url');
const querystring = require('querystring');

const server = http.createServer();

server.on('request', function (request, response) {
const parsedUrl = url.parse(request.url);
const parameters = querystring.parse(parsedUrl.query);

const result = faker.fake(parameters.template);

response.write(result);
response.end();
});

server.listen(3000);
console.log('Server is running.');

Restart the application:

$ curl -G "localhost:3000" --data-urlencode "template=Hello {{name.firstName}}"

Hello Fidel

Will we put more things in the application?

But before let’s put another dependency, the nodemon.

You probably are tired of restarting your application every time that you changed it. This will resolve this for us.

$ npm install --save-dev nodemon

Hint: Run the command with the option –save-dev, This will include automatically a dependency in your package.json, but, this time, in a section called devDependencies. It’s good to concentrate your libraries that are used only for development here.

And change the start in package.json.

{
"name": "fakemytemplate",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon index.js",
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"faker": "^3.1.0"
},
"devDependencies": {
"nodemon": "^1.9.2"
}
}

Now nodemon will restart the application every time that a file is changed.

Let’s add a new function: Every time that a server receives a POST, in the route /template, with a template in requisition’s body, it will answer with the result from faker.fake().

$ curl
-X POST
-H "Content-Type: application/json"
-d '{"template": "Hello {{name.firstName}}"}'
localhost:3000/template

Hello Steve

Let’s change in our handler of the request event.

const faker = require('faker');
const http = require('http');
const url = require('url');
const querystring = require('querystring');

const server = http.createServer();

function RootController(request, response) {
const parsedUrl = url.parse(request.url);
const parameters = querystring.parse(parsedUrl.query);

const result = faker.fake(parameters.template);

response.write(result);
response.end();
}

function TemplateController(request, response) {
/* handle the POST /template request here */
response.end();
}

const routes = {
'/': {
'GET': RootController
},
'/template': {
'POST': TemplateController
}
};

server.on('request', function (request, response) {
const parsedUrl = url.parse(request.url);

const routeHandler = routes[parsedUrl.pathname] &&
routes[parsedUrl.pathname][request.method];

return route(request, response);
});

server.listen(3000);
console.log('Server is running.');

As you can see, We did some kind of routing by URL path at parsedUrl.pathname and by the method (GET, POST, PUT…) request.method.

To make the association with the traditional MVC, We separated the code that treats the request and sends the answer in a separate function, that we label RootController.

You can see that objects request and response are passing to the controller for it get access to their own objects.

Let’s put a “default”. In the case that any controller is found to the route, it will send a status code 404. Not Found.

const faker = require('faker');
const http = require('http');
const url = require('url');
const querystring = require('querystring');

const server = http.createServer();

function RootController(request, response) {
const parsedUrl = url.parse(request.url);
const parameters = querystring.parse(parsedUrl.query);

const result = faker.fake(parameters.template);

response.write(result);
response.end();
}

function TemplateController(request, response) {
/* handle the POST /template request here */
response.end();
}

function NotFoundController(request, response) {
response.statusCode = 404;
response.write('Not found.');
response.end();
}

const routes = {
'/': {
'GET': RootController
},
'/template': {
'POST': TemplateController
}
};

server.on('request', function (request, response) {
const parsedUrl = url.parse(request.url);

const routeHandler = routes[parsedUrl.pathname] &&
routes[parsedUrl.pathname][request.method];

if (!routeHandler) {
return NotFoundController(request, response);
}

return routeHandler(request, response);
});

server.listen(3000);
console.log('Server is running.');

>Hint: Test the application in every modification. To make requests, I recommend the curl. If you are a command line person, use Postman, a Chrome plugin.

Now our index.js is big and confuse.

Let’s put these controllers in separate files.

We will create a folder named controllers, where We will have 3 controllers: root.js, template.js and the not_found.js.

And separate the routes too. We will create, at the root folder, an archive called routes.js.

The structure will be like that:

| controllers
| | not_found.js
| | root.js
| | template.js
|
| node_modules
| | ...
|
| index.js
| package.json
| router.js

We want a clean index.js. Without the controllers and routing.

/* ----- index.js ----- */

const http = require('http');
const router = require('./router');

const server = http.createServer();

server.on('request', function (request, response) {
router(request, response);
});

server.listen(3000);
console.log('Server is running.');

It looks much more simple now, right?

NDid you notice that we imported a module called router from ‘./router’. Node.JS follows the max specifications made at CommonJS. Including module’s specifications.

At specifications, notice that modules which are native from Node.JS or the modules that are installed at folder node_modules, need to be requested only by their name.
Example: require(‘http’) or require(‘faker’). For different modules, the path is necessary. At our example, the require(‘./router’) will look for the file router.js at the same folder where the application is running.

It’s time to migrate proper codes to the file. Starting with router.js.

/* ----- router.js ----- */

const url = require('url');

const RootController = require('./controllers/root');
const TemplateController = require('./controllers/template');
const NotFoundController = require('./controllers/not_found');

const routes = {
'/': {
'GET': RootController
},
'/template': {
'POST': TemplateController
}
};

function router(request, response) {
const parsedUrl = url.parse(request.url);

const routeHandler = routes[parsedUrl.pathname] &&
routes[parsedUrl.pathname][request.method];

if (!routeHandler) {
return NotFoundController(request, response);
}

return routeHandler(request, response);
}

module.exports = router;

Destaquei a última linha do código acima o module.exports.

This is a special object. This is where the object or value or function is associated with what we want the module to export. In this case, our router.js is exporting only the ffunction router.

So, when the module is imported at index.js…

/* ----- index.js ----- */

> const router = require('./router');

The variable router will receive the function router that we exported by module.exports.

We are also importing the controllers:

/* ----- router.js ----- */

> const RootController = require('./controllers/root');
> const TemplateController = require('./controllers/template');
> const NotFoundController = require('./controllers/not_found');

Let’s migrate the respective code controllers to the respective archives and export their functions.

/* ----- controllers/root_controller.js ----- */

const faker = require('faker');
const url = require('url');
const querystring = require('querystring');

function RootController(request, response) {
const parsedUrl = url.parse(request.url);
const parameters = querystring.parse(parsedUrl.query);

const result = faker.fake(parameters.template);

response.write(result);
response.end();
}

module.exports = RootController;

Do not forget to import faker, url and querystring.

/* ----- controllers/template_controller.js ----- */

function TemplateController(request, response) {
/* handle the POST /template request here */
response.end();
}

module.exports = TemplateController;

For now, it is not doing anything. Just finishing the answer. In a few steps, we’ll add new stuff there.

/* ----- controllers/not_found.js ----- */

function NotFoundController(request, response) {
response.statusCode = 404;
response.write('Not found.');
response.end();
}

module.exports = NotFoundController;

Will it work?

--- GET /
$ curl -G "localhost:3000"
--data-urlencode "template=Hello {{name.firstName}}"

Hello Trevor
--- POST /template
$ curl -X POST
-H "Content-Type: application/json"
-d '{"template": "Hello {{name.firstName}}"}'
localhost:3000/template

** This will not show anything. We are just finishing the answer. For now.**

--- GET /xablau (ou qualquer outro endereço)
$ curl localhost:3000/xablau

Not found.

Now We have a much nicer structure to go on and build the TemplateController who is still empty.

Currently:

/* ----- controllers/template_controller.js ----- */

function TemplateController(request, response) {
/* handle the POST /template request here */
response.end();
}

module.exports = TemplateController;

The first step is to get the body’s content of the request.

If you didn’t notice, the request is a stream, It’s an EventEmmiter instance. So you can put event’s listeners at the request.

At Node.JS, when receiving a request, it doesn’t wait for all content. To pick up all request’s information, We must wait for all content and only then extract what is necessary.

This is a very common behavior of Node.JS. Most operations involving I/O return Streams objects.

Basically, in this case, We are going to use two events. The data and end, to implement something like this.

Let’s create a function that receives two arguments: the object request and a callback. It will extract the body’s request content and, when finished, call the callback.

function extractBody(request, callback) {
let body = '';

request.setEncoding('utf-8');
request.on('data', (chunk) => body += chunk);
request.on('end', () => {
if (request.headers['content-type'] === 'application/json') {
return callback(JSON.parse(body));
}

return callback(body);
});
}

The let, used at let body = ‘’, define a variable that can be modified in the future. In our case, We’re modifying it at request.on(‘data’, (chunk) => body += chunk);

The syntax (chunk) => body += chunk is called Arrow Function. Is the same as function function (chunk) { return body += chunk; }. but shorter.

Notice that you used the Arrow Function after. But with {}. It’s used to put more than one line of code at Arrow Function block. Also, when We don’t use {} the return is implicit.

When We receive at the header that the Content-Type is application/json, We parse the body to return an object.

Let’s implement it at TemplateController. Make it create the template and send the result.

const faker = require('faker');

function extractBody(request, callback) {
let body = '';

request.setEncoding('utf-8');
request.on('data', (chunk) => body += chunk);
request.on('end', () => {
if (request.headers['content-type'] === 'application/json') {
return callback(JSON.parse(body));
}

return callback(body);
});
}

function TemplateController(request, response) {
extractBody(request, (body) => {
const result = faker.fake(body.template);

response.write(result);
response.end();
});
}

module.exports = TemplateController;

Beginners in Node.JS could find this very strange because We didn’t do this at TemplateController:

function TemplateController(request, response) {
const body = extractBody(request);
const result = faker.fake(body.template);

response.write(result);
response.end();
}

Remember: I/O operations are asynchronous. Even the data stream’s request. That’s why we should execute our code just when We receive all request content.

The callback’s model is very used at Node.JS to treat this type of asynchronous instructions. Where you will pass a function as an argument from other function and execute something asynchronous. Just then it callback the past function like an argument.

Let’s move this function extractBody to another file. Let’s create a folder called utils and make an archive extract_body.js inside.

/* ----- utils/extract_body.js ----- */

function extractBody(request, callback) {
let body = '';

request.setEncoding('utf-8');
request.on('data', (chunk) => body += chunk);
request.on('end', () => {
if (request.headers['content-type'] === 'application/json') {
return callback(JSON.parse(body));
}

return callback(body);
});
}

module.exports = extractBody;

Now We only have to import it at TemplateController.

/* ----- controllers/template.js ----- */

const faker = require('faker');
const extractBody = require('../utils/extract_body');

function TemplateController(request, response) {
extractBody(request, (body) => {
const template = body.template;
const result = faker.fake(template);

response.write(result);
response.end();
});
}

module.exports = TemplateController;

Test to see if everything is alright:

$ curl -X POST
-H "Content-Type: application/json"
-d '{"template": "Hello {{name.firstName}}"}'
localhost:3000/template

Hello Urban

To make it better, let’s use our TemplateController to send and answer in JSON.

const faker = require('faker');
const extractBody = require('../utils/extract_body');

function TemplateController(request, response) {
extractBody(request, (body) => {
const template = body.template;
const result = faker.fake(template);

response.setHeader(
'content-type', 'application/json; charset=UTF-8'
);

response.write(JSON.stringify({ result }));
response.end();
});
}

module.exports = TemplateController;

In JSON.stringify({ result }), you used a new function in ES6. So, { result } is equal { result: result }

$ curl -v -X POST
-H "Content-Type: application/json"
-d '{"template": "Hello {{name.firstName}}"}'
localhost:3000/template

< HTTP/1.1 200 OK
< content-type: application/json; charset=UTF-8
< Date: Wed, 08 Jun 2016 14:15:35 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked

{"result":"Hello Junius"}

That was a long journey but you learn to create a small Node.JS application.

We have a lot of things to adjust: Treat the errors that could happen in fake.fake(), answer correctly with 400 Bad Request, make our RootController show a ReadMe explaining how to use de service or write tests Just some examples of what we can do better.

You don't need to use only native Node.JS modules. That are frameworks and libraries that make the same thing we did here, but easier. Take a look at koa.js or restify,at drives of mongodb, mysql and postgres. Explore the npm.

You can see our final code here

See you!