Bulletproof node.js project architecture

Bulletproof node.js project architecture

This article is extense research, from my years of experience dealing with a poor structured node.js project, bad patterns, and countless hours of refactoring code and moving things around.

Introduction

Express.js is great frameworks for making a node.js REST APIs however it doesn’t give you any clue on how to organizing your node.js project.

While it may sound silly, this is a real problem.

The correct organization of your node.js project structure will avoid duplication of code, will improve stability, and potentially, will help you scale your services if is done correctly.


Table of contents
  • The folder structure 🏢
  • 3 Layer architecture 🥪
  • Service Layer 💼
  • Pub/Sub Layer ️️️️🎙️️
  • Dependency Injection 💉
  • Unit Testing 🕵🏻
  • Cron Jobs and recurring task ⚡
  • Configurations and secrets 🤫
  • Loaders 🏗️
  • Example Repository



The folder structure 🏢

Here is the node.js project structure that I’m talking about.

I use this in every node.js REST API service that I build, let’s see in details what every component do.

  src
  │   app.js          # App entry point
  └───api             # Express route controllers for all the endpoints of the app
  └───config          # Environment variables and configuration related stuff
  └───jobs            # Jobs definitions for agenda.js
  └───loaders         # Split the startup process into modules
  └───models          # Database models
  └───services        # All the business logic is here
  └───subscribers     # Event handlers for async task
  └───types           # Type declaration files (d.ts) for Typescript

It is more than just a way of ordering javascript files…



3 Layer architecture 🥪

The idea is to use the principle of separation of concerns to move the business logic away from the node.js API Routes.

Because someday, you will want to use your business logic on a CLI tool, or not going far, in a recurring task.

And make an API call from the node.js server to itself it’s not a good idea…


☠️ Don’t put your business logic inside the controllers!! ☠️

You may be tempted to just use the express.js controllers to store the business logic of your application, but this quickly becomes spaghetti code, as soon as you need to write unit tests, you will end up dealing with complex mocks for req or res express.js objects.

It’s complicated to distingue when a response should be sent, and when to continue processing in ‘background’, let’s say after the response is sent to the client.

Here is an example of what not to do.

  route.post('/', async (req, res, next) => {

// This should be a middleware or should be handled by a library like Joi.
const userDTO = req.body;
const isUserValid = validators.user(userDTO)
if(!isUserValid) {
  return res.status(400).end();
}

// Lot of business logic here...
const userRecord = await UserModel.create(userDTO);
delete userRecord.password;
delete userRecord.salt;
const companyRecord = await CompanyModel.create(userRecord);
const companyDashboard = await CompanyDashboard.create(userRecord, companyRecord);

...whatever...

// And here is the 'optimization' that mess up everything.
// The response is sent to client...
res.json({ user: userRecord, company: companyRecord });

// But code execution continues :(
const salaryRecord = await SalaryModel.create(userRecord, companyRecord);
eventTracker.track('user_signup',userRecord,companyRecord,salaryRecord);
intercom.createUser(userRecord);
gaAnalytics.event('user_signup',userRecord);
await EmailService.startSignupSequence(userRecord)

});



Use a service layer for your business logic 💼

This layer is where your business logic should live.

It’s just a collection of classes with clear porpuses, following the SOLID principles applied to node.js.

In this layer there should not exists any form of ‘SQL query’, use the data access layer for that.

  • Move your code away from the express.js router
  • Don’t pass the req or res object to the service layer
  • Don’t return anything related to the HTTP transport layer like a status code or headers from the service layer.

Example

  route.post('/',
validators.userSignup, // this middleware take care of validation
async (req, res, next) => {
// The actual responsability of the route layer.
const userDTO = req.body;

  // Call to service layer.
  // Abstraction on how to access the data layer and the business logic.
  const { user, company } = await UserService.Signup(userDTO);

  // Return a response to client.
  return res.json({ user, company });
});

Here is how your service will be working behind the scenes.

  import UserModel from '../models/user';
import CompanyModel from '../models/company';

export default class UserService() {

async Signup(user) {
  const userRecord = await UserModel.create(user);
  const companyRecord = await CompanyModel.create(userRecord); // needs userRecord to have the database id 
  const salaryRecord = await SalaryModel.create(userRecord, companyRecord); // depends on user and company to be created

  ...whatever

  await EmailService.startSignupSequence(userRecord)

  ...do more stuff

  return { user: userRecord, company: companyRecord };
}

}

Visit the example repository



Use a Pub/Sub layer too 🎙️

The pub/sub pattern goes beyond the classic 3 layer architecture proposed here but it’s extremely useful.

The simple node.js API endpoint that creates a user right now, may want to call third-party services, maybe to an analytics service, or maybe start an email sequence.

Sooner than later, that simple “create” operation will be doing several things, and you will end up with 1000 lines of code, all in a single function.

That violates the principle of single responsibility.

So, it’s better to separate responsibilities from the start, so your code remains maintainable.

  import UserModel from '../models/user';
import CompanyModel from '../models/company';
import SalaryModel from '../models/salary';

export default class UserService() {

async Signup(user) {
  const userRecord = await UserModel.create(user);
  const companyRecord = await CompanyModel.create(user);
  const salaryRecord = await SalaryModel.create(user, salary);

  eventTracker.track(
    'user_signup',
    userRecord,
    companyRecord,
    salaryRecord
  );

  intercom.createUser(
    userRecord
  );

  gaAnalytics.event(
    'user_signup',
    userRecord
  );

  await EmailService.startSignupSequence(userRecord)

  ...more stuff

  return { user: userRecord, company: companyRecord };
}

}

An imperative call to a dependent service is not the best way of doing it.

A better approach is by emitting an event i.e. ‘a user signed up with this email’.

And you are done, now it’s the responsibility of the listeners to do their job.

  import UserModel from '../models/user';
import CompanyModel from '../models/company';
import SalaryModel from '../models/salary';

export default class UserService() {

async Signup(user) {
  const userRecord = await this.userModel.create(user);
  const companyRecord = await this.companyModel.create(user);
  this.eventEmitter.emit('user_signup', { user: userRecord, company: companyRecord })
  return userRecord
}

}

Now you can split the event handlers/listeners into multiple files.

  eventEmitter.on('user_signup', ({ user, company }) => {

eventTracker.track(
  'user_signup',
  user,
  company,
);

intercom.createUser(
  user
);

gaAnalytics.event(
  'user_signup',
  user
);

})

eventEmitter.on('user_signup', async ({ user, company }) => {
const salaryRecord = await SalaryModel.create(user, company);
})

eventEmitter.on('user_signup', async ({ user, company }) => {
await EmailService.startSignupSequence(user)
})

You can wrap the await statements into a try-catch block or you can just let it fail and handle the ‘unhandledPromise’ process.on(‘unhandledRejection’,cb)



Dependency Injection 💉

D.I. or inversion of control (IoC) is a common pattern that will help the organization of your code, by ‘injecting’ or passing through the constructor the dependencies of your class or function.

By doing this way you will gain the flexibility to inject a ‘compatible dependency’ when, for example, you write the unit tests for the service, or when the service is used in another context.

Code with no D.I

  import UserModel from '../models/user';
import CompanyModel from '../models/company';
import SalaryModel from '../models/salary';
class UserService {
constructor(){}
Sigup(){
// Caling UserMode, CompanyModel, etc
...
}
}

Code with manual dependency injection

  export default class UserService {
constructor(userModel, companyModel, salaryModel){
this.userModel = userModel;
this.companyModel = companyModel;
this.salaryModel = salaryModel;
}
getMyUser(userId){
// models available throug 'this'
const user = this.userModel.findById(userId);
return user;
}
}

Now you can inject custom dependencies.

  import UserService from '../services/user';
import UserModel from '../models/user';
import CompanyModel from '../models/company';
const salaryModelMock = {
calculateNetSalary(){
return 42;
}
}
const userServiceInstance = new UserService(userModel, companyModel, salaryModelMock);
const user = await userServiceInstance.getMyUser('12346');

The amount of dependencies a service can have is infinite, and refactor every instantiation of it when you add a new one is a boring and error-prone task.

That’s why dependency injection frameworks were created.

The idea is you declare your dependencies in the class, and when you need an instance of that class, you just call the ‘Service Locator’.

Let’s see an example using typedi an npm library that brings D.I to node.js

You can read more on how to use typedi in the official documentation

WARNING typescript example

  import { Service } from 'typedi';
@Service()
export default class UserService {
constructor(
private userModel,
private companyModel,
private salaryModel
){}

getMyUser(userId){
  const user = this.userModel.findById(userId);
  return user;
}

}

services/user.ts

Now typedi will take care of resolving any dependency the UserService require.

  import { Container } from 'typedi';
import UserService from '../services/user';
const userServiceInstance = Container.get(UserService);
const user = await userServiceInstance.getMyUser('12346');

Abusing service locator calls is an anti-pattern


Using Dependency Injection with Express.js in Node.js

Using D.I. in express.js is the final piece of the puzzle for this node.js project architecture.

Routing layer

  route.post('/',
async (req, res, next) => {
const userDTO = req.body;

  const userServiceInstance = Container.get(UserService) // Service locator

  const { user, company } = userServiceInstance.Signup(userDTO);

  return res.json({ user, company });
});

Awesome, project is looking great!

It’s so organized that makes me want to be coding something right now.

Visit the example repository



An unit test example 🕵🏻

By using dependency injection and these organization patterns, unit testing becomes really simple.

You don’t have to mock req/res objects or require(…) calls.

Example: Unit test for signup user method

tests/unit/services/user.js

  import UserService from '../../../src/services/user';

describe('User service unit tests', () => {
describe('Signup', () => {
test('Should create user record and emit user_signup event', async () => {
const eventEmitterService = {
emit: jest.fn(),
};

    const userModel = {
      create: (user) => {
        return {
          ...user,
          _id: 'mock-user-id'
        }
      },
    };

    const companyModel = {
      create: (user) => {
        return {
          owner: user._id,
          companyTaxId: '12345',
        }
      },
    };

    const userInput= {
      fullname: 'User Unit Test',
      email: '[email protected]',
    };

    const userService = new UserService(userModel, companyModel, eventEmitterService);
    const userRecord = await userService.SignUp(teamId.toHexString(), userInput);

    expect(userRecord).toBeDefined();
    expect(userRecord._id).toBeDefined();
    expect(eventEmitterService.emit).toBeCalled();
  });
})

})



Cron Jobs and recurring task ⚡

So, now that the business logic encapsulated into the service layer, it’s easier to use it from a Cron job.

You should never rely on node.js setTimeout or another primitive way of delay the execution of code, but on a framework that persist your jobs, and the execution of them, in a database.

This way you will have control over the failed jobs, and feedback of those who succeed.

I already wrote on good practice for this so, check my guide on using agenda.js the best task manager for node.js.



Configurations and secrets 🤫

Following the battle-tested concepts of Twelve-Factor App for node.js the best approach to store API Keys and database string connections, it’s by using dotenv.

Put a .env file, that must never be committed (but it has to exist with default values in your repository) then, the npm package dotenv loads the .env file and insert the vars into the process.env object of node.js.

That could be enough but, I like to add an extra step.

Have a config/index.ts file where the dotenv npm package and loads the .env file and then I use an object to store the variables, so we have a structure and code autocompletion.

config/index.js

  const dotenv = require('dotenv');
// config() will read your .env file, parse the contents, assign it to process.env.
dotenv.config();

export default {
port: process.env.PORT,
databaseURL: process.env.DATABASE_URI,
paypal: {
publicKey: process.env.PAYPAL_PUBLIC_KEY,
secretKey: process.env.PAYPAL_SECRET_KEY,
},
paypal: {
publicKey: process.env.PAYPAL_PUBLIC_KEY,
secretKey: process.env.PAYPAL_SECRET_KEY,
},
mailchimp: {
apiKey: process.env.MAILCHIMP_API_KEY,
sender: process.env.MAILCHIMP_SENDER,
}
}

This way you avoid flooding your code with process.env.MY_RANDOM_VAR instructions, and by having the autocompletion you don’t have to know how to name the env var.

Visit the example repository



Loaders 🏗️

I took this pattern from W3Tech microframework but without depending upon their package.

The idea is that you split the startup process of your node.js service into testable modules.

Let’s see a classic express.js app initialization

  const mongoose = require('mongoose');
const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const cors = require('cors');
const errorhandler = require('errorhandler');
const app = express();

app.get('/status', (req, res) => { res.status(200).end(); });
app.head('/status', (req, res) => { res.status(200).end(); });
app.use(cors());
app.use(require('morgan')('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json(setupForStripeWebhooks));
app.use(require('method-override')());
app.use(express.static(__dirname + '/public'));
app.use(session({ secret: process.env.SECRET, cookie: { maxAge: 60000 }, resave: false, saveUninitialized: false }));
mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true });

require('./config/passport');
require('./models/user');
require('./models/company');
app.use(require('./routes'));
app.use((req, res, next) => {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
app.use((err, req, res) => {
res.status(err.status || 500);
res.json({'errors': {
message: err.message,
error: {}
}});
});

... more stuff

... maybe start up Redis

... maybe add more middlewares

async function startServer() {
app.listen(process.env.PORT, err => {
if (err) {
console.log(err);
return;
}
console.log(Your server is ready !);
});
}

// Run the async function to start our server
startServer();

As you see, this part of your application can be a real mess.

Here is an effective way to deal with it.

  const loaders = require('./loaders');
const express = require('express');

async function startServer() {

const app = express();

await loaders.init({ expressApp: app });

app.listen(process.env.PORT, err => {
  if (err) {
    console.log(err);
    return;
  }
  console.log(`Your server is ready !`);
});

}

startServer();

Now the loaders are just tiny files with a concise purpose

loaders/index.js

  import expressLoader from './express';
import mongooseLoader from './mongoose';

export default async ({ expressApp }) => {
const mongoConnection = await mongooseLoader();
console.log('MongoDB Intialized');
await expressLoader({ app: expressApp });
console.log('Express Intialized');

// ... more loaders can be here

// ... Initialize agenda
// ... or Redis, or whatever you want

}

The express loader

loaders/express.js

  import * as express from 'express';
import * as bodyParser from 'body-parser';
import * as cors from 'cors';

export default async ({ app }: { app: express.Application }) => {

app.get('/status', (req, res) => { res.status(200).end(); });
app.head('/status', (req, res) => { res.status(200).end(); });
app.enable('trust proxy');

app.use(cors());
app.use(require('morgan')('dev'));
app.use(bodyParser.urlencoded({ extended: false }));

// ...More middlewares

// Return the express app
return app;

})

The mongo loader

loaders/mongoose.js

  import * as mongoose from 'mongoose'
export default async (): Promise<any> => {
const connection = await mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true });
return connection.connection.db;
}

See a complete example of loaders here



Conclusion

We deep dive into a production tested node.js project structure, here are some summarized tips:

  • Use a 3 layer architecture.
  • Don’t put your business logic into the express.js controllers.
  • Use PubSub pattern and emit events for background tasks.
  • Have dependency injection for your peace of mind.
  • Never leak your passwords, secrets and API keys, use a configuration manager.
  • Split your node.js server configurations into small modules that can be loaded independently.

Thanks for reading ❤

If you liked this post, share it with all of your programming buddies!

Follow me on Facebook | Twitter

Learn More

The Complete Node.js Developer Course (3rd Edition)

Angular & NodeJS - The MEAN Stack Guide

NodeJS - The Complete Guide (incl. MVC, REST APIs, GraphQL)

Node.js: The Complete Guide to Build RESTful APIs (2018)

Learn and Understand NodeJS

MERN Stack Front To Back: Full Stack React, Redux & Node.js

Node, Express, Angular 7, GraphQL and MongoDB CRUD Web App

Node, Express, React.js, Graphql and MongoDB CRUD Web Application

A to Z of Node.js Packages(unconventional)

Top Mistakes That Node.js Developers Make and Should be Avoided

Google’s Go Essentials For Node.js / JavaScript Developers

Angular + WebSocket + Node.js Express = RxJS WebSocketSubject ❤️

Originaly posted on softwareontheroad.com

Top 7 Most Popular Node.js Frameworks You Should Know

Top 7 Most Popular Node.js Frameworks You Should Know

Node.js is an open-source, cross-platform, runtime environment that allows developers to run JavaScript outside of a browser. In this post, you'll see top 7 of the most popular Node frameworks at this point in time (ranked from high to low by GitHub stars).

Node.js is an open-source, cross-platform, runtime environment that allows developers to run JavaScript outside of a browser.

One of the main advantages of Node is that it enables developers to use JavaScript on both the front-end and the back-end of an application. This not only makes the source code of any app cleaner and more consistent, but it significantly speeds up app development too, as developers only need to use one language.

Node is fast, scalable, and easy to get started with. Its default package manager is npm, which means it also sports the largest ecosystem of open-source libraries. Node is used by companies such as NASA, Uber, Netflix, and Walmart.

But Node doesn't come alone. It comes with a plethora of frameworks. A Node framework can be pictured as the external scaffolding that you can build your app in. These frameworks are built on top of Node and extend the technology's functionality, mostly by making apps easier to prototype and develop, while also making them faster and more scalable.

Below are 7of the most popular Node frameworks at this point in time (ranked from high to low by GitHub stars).

Express

With over 43,000 GitHub stars, Express is the most popular Node framework. It brands itself as a fast, unopinionated, and minimalist framework. Express acts as middleware: it helps set up and configure routes to send and receive requests between the front-end and the database of an app.

Express provides lightweight, powerful tools for HTTP servers. It's a great framework for single-page apps, websites, hybrids, or public HTTP APIs. It supports over fourteen different template engines, so developers aren't forced into any specific ORM.

Meteor

Meteor is a full-stack JavaScript platform. It allows developers to build real-time web apps, i.e. apps where code changes are pushed to all browsers and devices in real-time. Additionally, servers send data over the wire, instead of HTML. The client renders the data.

The project has over 41,000 GitHub stars and is built to power large projects. Meteor is used by companies such as Mazda, Honeywell, Qualcomm, and IKEA. It has excellent documentation and a strong community behind it.

Koa

Koa is built by the same team that built Express. It uses ES6 methods that allow developers to work without callbacks. Developers also have more control over error-handling. Koa has no middleware within its core, which means that developers have more control over configuration, but which means that traditional Node middleware (e.g. req, res, next) won't work with Koa.

Koa already has over 26,000 GitHub stars. The Express developers built Koa because they wanted a lighter framework that was more expressive and more robust than Express. You can find out more about the differences between Koa and Express here.

Sails

Sails is a real-time, MVC framework for Node that's built on Express. It supports auto-generated REST APIs and comes with an easy WebSocket integration.

The project has over 20,000 stars on GitHub and is compatible with almost all databases (MySQL, MongoDB, PostgreSQL, Redis). It's also compatible with most front-end technologies (Angular, iOS, Android, React, and even Windows Phone).

Nest

Nest has over 15,000 GitHub stars. It uses progressive JavaScript and is built with TypeScript, which means it comes with strong typing. It combines elements of object-oriented programming, functional programming, and functional reactive programming.

Nest is packaged in such a way it serves as a complete development kit for writing enterprise-level apps. The framework uses Express, but is compatible with a wide range of other libraries.

LoopBack

LoopBack is a framework that allows developers to quickly create REST APIs. It has an easy-to-use CLI wizard and allows developers to create models either on their schema or dynamically. It also has a built-in API explorer.

LoopBack has over 12,000 GitHub stars and is used by companies such as GoDaddy, Symantec, and the Bank of America. It's compatible with many REST services and a wide variety of databases (MongoDB, Oracle, MySQL, PostgreSQL).

Hapi

Similar to Express, hapi serves data by intermediating between server-side and client-side. As such, it's can serve as a substitute for Express. Hapi allows developers to focus on writing reusable app logic in a modular and prescriptive fashion.

The project has over 11,000 GitHub stars. It has built-in support for input validation, caching, authentication, and more. Hapi was originally developed to handle all of Walmart's mobile traffic during Black Friday.

Node.js Tutorial for Beginners | Node.js Crash Course | Node.js Certification Training

This courseis designed for professionals who aspire to be application developers and gain expertise in building real-time, highly-scalable applications in Node.js. The following professionals can go for this course :

Why learn Node.js?

Node.js uses JavaScript - a language known to millions of developers worldwide - thus giving it a much lower learning curve even for complete beginners. Using Node.js you can build simple Command Line programs or complex enterprise level web applications with equal ease. Node.js is an event-driven, server-side, asynchronous development platform with lightning speed execution. Node.js helps you to code the most complex functionalities in just a few lines of code...

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

The Complete Node.js Developer Course (3rd Edition)

Angular & NodeJS - The MEAN Stack Guide

NodeJS - The Complete Guide (incl. MVC, REST APIs, GraphQL)

Docker for Node.js Projects From a Docker Captain

Intro To MySQL With Node.js - Learn To Use MySQL with Node!

Node.js Absolute Beginners Guide - Learn Node From Scratch

React Node FullStack - Social Network from Scratch to Deploy

Selenium WebDriver - JavaScript nodeJS webdriver IO & more!

Complete Next.js with React & Node - Beautiful Portfolio App

Build a Blockchain & Cryptocurrency | Full-Stack Edition

A Beginner Guide To Node.js (Basic Introduction To Node.js)

Node.js is a very popular javascript free and open source cross-platform for server-side programming built on Google Chrome’s Javascript V8 Engine. It is used by thousands of developers around the world to develop mobile and web applications. According to StackOverflow survey, Node.js is one of most famous choice for building the web application in 2018.

Introduction

Node.js is a very popular javascript free and open source cross-platform for server-side programming built on Google Chrome’s Javascript V8 Engine. It is used by thousands of developers around the world to develop mobile and web applications. According to StackOverflow survey, Node.js is one of most famous choice for building the web application in 2018.

In this article, you will gain a deep understanding of node, learn how node.js works and why it is so popular among the developers and startups. Not In startup even big companies like eBay, Microsoft, GoDaddy, Paypal etc.

Why is Node.js so much popular

It is fast very fast

It’s a javascript runtime built on google chrome javascript v8 engine which means both node js and js executed in your browser running in the same engine that makes it very fast in comparison to any other server-side programming language.

It uses event-driven and non-blocking model

Node.js uses the event-driven, non-blocking I/O model that makes it very lightweight and efficient.
Now let’s understand the above statement in more details. Here I/O refers to Input /Output.

Event Driven Programming is a paradigm in which control flow of any program is determined by the occurrence of the events. All these events monitor by the code which is known as an event listener. If you are from javascript background then most probably you know what is event-listeners. In short, event-listener is a procedure or function that waits for an event to occurs. In javascript, onload, onclick, onblur most common event-listener.

**Blocking I/O **takes time and hence block other function. Consider the scenario where we want to fetch data from the database for two different users. Here we can not get the data of the second user until we did not complete the first user process. Since javascript is a single threaded and here we would have to start a new thread every time we want to fetch user data. So here Non-Blocking I/O parts come in.

Example of Blocking I/O operation

<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(‘fs’);
<span class="hljs-keyword">var</span> contents = fs.readFileSync(<span class="hljs-string">'package.json'</span>).toString();
<span class="hljs-built_in">console</span>.log(contents);

In** Non-blocking I/O **operations, you can get the user2 data without waiting for the completion of the user1 request. You can initiate both requests in parallel. **Non-blocking I/O **eliminates the need for the multi-threaded, since the system can handle multiple requests at the same time. That is the main reason which makes it very fast.

Example of Non-blocking I/O operation

<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(‘fs’);
fs.readFile(<span class="hljs-string">'package.json'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, buf</span>)</span>{
    <span class="hljs-built_in">console</span>.log(buf.toString());
});

Note: You can learn more about the event loop and other things by going through this link.

What is Node Package Manager ( NPM )

It is is the official package manager for the node. It bundles automatically installed when you install node in your system. It is used to install new packages and manage them in useful ways. NPM install packages in two modes local and global. In the local mode, NPM installs packages in the node_module directory of the current working directory which location is owned by current user. Global packages installed in the directory where the node is installed and the location is owned by the root user.

What is the package.json

package.json is a plain JSON text file which manages all the packaged which you installed in your node application. Every Node.js applications should have this file at the root directory to describe the application metadata. A simple package.json file looks like below

{
    <span class="hljs-string">"name"</span> : <span class="hljs-string">"codesquery"</span>,
    <span class="hljs-string">"version"</span> : <span class="hljs-string">"1.0.0"'
    "repository": {
	"type" : "git",
	"url" : "github_repository_url"
    },
    "dependencies": {
	"async": "0.8.0",
	"express": "4.2.x"
    }
}
</span>

In the above file, name and versions are mandatory for the package.json file and rest is optional.

Installing Node.js

  • In Windows, you can install the node.js by using the installer provided by the official node.js website. Follow the installer instruction and node.js will be installed in your windows system.
  • In Linux OS, you can install the node.js by adding the PPA in your system and then install node js. Run the below command the terminal to install node js
sudo apt-get install curl python-software-properties
curl -sL https:<span class="hljs-comment">//deb.nodesource.com/setup_10.x | sudo -E bash -</span>
sudo apt-get install nodejs

  • In macOS, download the macOS installer from the official node.js website. Now run the installer by accepting the license and selecting the destination.

Test Node.js Installation

You can test the node.js installation by typing below command in the terminal

node -v

If node.js was installed successfully then you will see the installed version of the node in the terminal.

Frameworks and Tools

After gaining the popularity among the developers, there are so many frameworks built for the node js for the different type of uses. Here, I will tell you some of the most famous node js frameworks in the market

  • Express.js is the most popular framework for node.js development. A lot of popular websites is powered by express.js due to its lightweight.
  • Hapi.js is a powerful and robust framework for developing the API. This framework has features like input validation, configuration based functionality, error handling, caching and logging.
  • Metor.js is one of the most used frameworks in the node js web application development. This framework is backed by a huge community of developers, tutorials and good documentation.
  • Socket.io is used to build a real-time web application like chat system and analytics. Its allow the bi-direction data flow between the web client and server.
  • Koa.js is yet another most used framework to build the web application using the node js. This framework is backed by the team behind Express.js. It allows you to ditch callbacks and increase error handling.

Conclusion

Today, Node.js shaping the future of web and application development technology. This is the just the basic of how node js works. If you want to build a scalable web application using the node js then you need to know more then this.

Till now, you have got the basic idea of node.js and now it is time to build something using the node.js. You can start with first by create a simple server using the node.js and then connect your node with MongoDB to perform the basic crud operation.