Back-end10-minute read

Express, Koa, Meteor, Sails.js: A Node.js Framework Comparison

Some platforms have an overwhelming number of options for web frameworks. Node.js, the event-driven server-side JavaScript environment, is one such platform. Whether it’s the minimalist Express or the full-blown MVC web framework Sails.js, Node.js seems to have it all.

In this article, Toptal Freelance Software Engineer Chuoxian Yang explores four of the most popular Node.js web frameworks and discusses how each framework stands out from the rest of the crowd in Node.js.


Toptalauthors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.

Some platforms have an overwhelming number of options for web frameworks. Node.js, the event-driven server-side JavaScript environment, is one such platform. Whether it’s the minimalist Express or the full-blown MVC web framework Sails.js, Node.js seems to have it all.

In this article, Toptal Freelance Software Engineer Chuoxian Yang explores four of the most popular Node.js web frameworks and discusses how each framework stands out from the rest of the crowd in Node.js.


Toptalauthors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
Chuoxian Yang
Verified Expert in Engineering

Chuoxian is a full-stack developer and tech company founder who has built multiple large-scale projects from blueprint to launch.

Previously At

Blackthorn
Share

JavaScript has definitely become one of the most popular languages in recent years, due to the humongous demand for web applications. While coding for multiple browsers, JavaScript is almost the only choice for front-end developers. One may argue that there’s CoffeeScript, TypeScript or Dart as alternatives. However, the truth is that CoffeeScript is mostly viewed as a syntactic sugar that eventually boils down to JavaScript. TypeScript is simply a superset of JavaScript that includes several object-oriented language features, such as optional static typing, classes and interfaces, and it’s still in it’s early days. Dart is also an object-oriented language which has C-like syntax, but it still compiles to JavaScript for mainstream browsers.

With the birth and rapid growth of Node.js, JavaScript is no longer confined to front-end development anymore. With the introduction of Node.js back-end frameworks, back-end development is no longer rocket science for front-end coders. People tend to think of JavaScript as a silver bullet that fits in all situations: front-end, web server, desktop application, embedded system, databases … the list just keeps getting longer. In fact, given the widespread audiences of JavaScript, Node.js+MongoDB+AngularJS/React has made quite a large amount of full stack web developers. However, Node.js is designed to be lightweight and provides only fundamental functionalities as a web server to boost web application development speed. One of the good-to-go frameworks that are available as npm packages would be a better option in the real world.

In this post, we will walk through some of these well known and time tested Node.js frameworks that have relieved developers from having to reinvent the wheel over and over. To be more specific, in this article we will take a look at Express, Koa, Meteor and Sails.js. Instead of trying to figure out how each of these frameworks stack against one another, we will see the key areas in which each of these frameworks excel and how they are relevant to various project needs.

Express: A Minimalist Node.js Web Framework

It goes without saying that Express is the biggest deal for Node.js business. Every Node.js player has heard of it and is using it with or without noticing. It’s currently on its 4th generation, and there are quite a few Node.js frameworks built based upon it or inspired by its concepts.

Performance

Most developers adore Node.js for its raw speed, and when it comes down to framework selection, a perfectionist may disdain any performance jeopardy. Express provides a thin layer on top of Node.js with web application features such as basic routing, middleware, template engine and static files serving, so the drastic I/O performance of Node.js doesn’t get compromised.

Express is a minimal, un-opinionated Node.js framework. it doesn’t apply any of the prevalent design patterns such as MVC, MVP, MVVM or whatever is trending out of the box. For fans of simplicity, this is a big plus among all other frameworks because you can build your application with your own preference and no unnecessary learning curve. This is especially advantageous when creating a new personal project with no historical burden, but as the project or developing team grows, lack of standardization may lead to extra work for project/code management, and worst case scenario it may lead to the inability to maintain.

Generator

Even though Express is not an opinionated Node.js framework, it does have the generator that generates specific project folder structure. After installing express-generator npm package and creating application skeleton with generator command, an application folder with clear hierarchy will be created to help you organize images, front-end static JavaScript, stylesheet files and HTML template files.

npm install express-generator -g
express helloapp

   create : helloapp
   create : helloapp/package.json
   create : helloapp/app.js
   create : helloapp/public
   create : helloapp/public/images
   create : helloapp/routes
   create : helloapp/routes/index.js
   create : helloapp/routes/users.js
   create : helloapp/public/stylesheets
   create : helloapp/public/stylesheets/style.css
   create : helloapp/views
   create : helloapp/views/index.jade
   create : helloapp/views/layout.jade
   create : helloapp/views/error.jade
   create : helloapp/bin
   create : helloapp/bin/www

   install dependencies:
     $ cd helloapp && npm install

   run the app:
     $ DEBUG=helloapp:* npm start

   create : helloapp/public/javascripts

Middleware

Middleware are basically just functions that have full access to both request and response objects.

Request handling stack

As the name implies, middleware applies some filtering instruction before handing the control over to actual business logic or the next level of middleware. Some common tasks include like checking for user login status, validating user authority, or preventing cross-site attacks are best extracted as middleware.

var app = express();

app.use(cookieParser());
app.use(bodyParser());
app.use(logger());
app.use(authentication());

app.get('/', function (req, res) {
  // ...
});

app.listen(3000);

An Express application is essentially Node.js with a host of middleware functions, whether you want to customize your own middleware or take advantage of the built-in middlewares of the framework, Express made the process natural and intuitive.

Template Engine

Template engines allow developer to embed backend variables into HTML files, and when requested the template file will be rendered to plain HTML format with the variables interpolated with their actual values. By default, the express-generator uses Pug (originally known as Jade) template engine, but other options like Mustache and EJS also work with Express seamlessly.

Database Integration

As a minimal framework, Express does not consider database integration as a required aspect within its package, thus it leans toward no specific database usage whatsoever. While adopting a particular data storage technology, be it MySQL, MongoDB, PostgreSQL, Redis, ElasticSearch or something else, it’s just a matter of installing the particular npm package as database driver. These third party database drivers do not conform to unified syntax when doing CRUD instructions, which makes switching databases a big hassle and error prone.

Koa: Utilizing Next Generation JavaScript Features

Koa is developed by the team behind Express, and its goal is to minimize the minimalist Express by not bundling any middleware within its core. Other than being middleware-less, Koa looks very similar to Express, lightweight and un-opinionated. However, what makes Koa truly standout is its way to ditch callback completely by using the ES6 Generator feature.

Elegant Control Flow

Javascript is an asynchronous programming language, and with such instinct of the language itself and the single threaded event-driven mechanism of Node.js, callback is all over the place, hence the notorious callback hell.

One way to flatten callback nesting is to use Async.js. Async.js provides techniques to map, parallelize, serialize or iterate multiple functions without having to embed one into another and then pass over the control flow with a callback function, one callback and one error handling function is enough for the bulk of functions grouped together by an Async.js method. Yet Async.js cannot wipe out callbacks entire. When writing Node.js code with Async.js, the indentation of code still tends to drift to the right, just not as deep.

Escape from callback hell

Another cleaner way is to use then-able Promises. Some third party Promise libraries with reputation are bluebird and q. In the newest edition of JavaScript, ES6, Promise has been taken in as a standardization. Long story short, Promise guarantees that functions are executed and returned in a sequential way by connecting the implementation blocks/functions with a bunch of Promise “then” functions. You either “resolve” at the end of each implementation block/function so that the next “then” function gets executed, or you “reject” the following implementation so that the control flow jumps right to error handling. This way, you aggregate all error handling functions to one place and get rid of callbacks thoroughly.

Now ES6 brings a game changer to the table — ES6 Generator. This notion is new to JavaScript, but not new in the programming world at all. ES6 Generator is like interruption in C, instead of running lines of code all the way from top to bottom, ES6 Generator introduces a means to run->halt and run something else->come back to finish what is leftover.

Koa is utilizing ES6 Generators to provide an elegant way to cope with JavaScript asynchronous programming, thus you cannot see callbacks in a pure Koa application. One typical use case of ES6 Generator in Koa is middleware cascading, which allows customized middleware to execute one after another without any nasty callbacks.

var app = koa();

function* responseTimeLogger(next){
  var start = new Date;
  yield next;
  var ms = new Date - start;
  console.log(this.method + ' ' + this.url + ': ' + ms);
}

app.use(responseTimeLogger);

// ...

app.listen(3000);

We cannot jump to conclusions asserting that this cutting-edge technique is superior to old school solutions such as Async.js, Promise or event emitter, but one thing is for sure that this new concept does take some time to get used to. With the unconventional control flow sequence, it could bring extra difficulty to code debugging.

Meteor: Framework For Web, Mobile And Desktop

Meteor is an all-in-one JavaScript framework. Differentiating from Express and Koa’s simplification philosophy, it goes to the other extreme by defining itself as a full-stack framework, a full package that covers server, mobile, desktop and web apps.

One-for-all Package

If you look closely under the hood, you will notice that Meteor is really Node.js+Blaze/AngularJS/React+Cordova+MongoDB. Node.js and MongoDB are respectively responsible for server side business logic and data storage. One of Blaze, AngularJS, or React takes care of front-end UI. And Cordova, as the most famous HTML solution for mobile hybrid apps, bridges web pages to mobile views.

Data Synchronization

The mainstream process for backend and front-end to share data is as follows:

  • Client requests data or certain HTML view
  • Server retrieves data from database, mixes data with HTML view using some templating engine and sends it back to the front-end
  • Client renders and shows the data/view in a user-friendly way

A modern single page web application tweaks the above process a little. Take AngularJS as an example, it puts HTML templates as static files together with other assets such as front-end JavaScript files, stylesheets and images. AngularJS then fills the data into the HTML templates by asking the back-end for data using Ajax RESTful API. Either way, back-end developers are fully responsible for handling data change requests from the front-end and saving changes in the database.

bi-directional data synchronization accomplished automatically

One of the features that distinguishes Meteor from other frameworks is its data synchronization mechanism among server and front-end/mobile apps. In Meteor, the client holds a mini-database shadow copy which is a small portion of replication from server database, a portion that is previously requested by the client and is authorized by server. When the client wants to make any changes to the data, it uses the consistent database API as server side to perform any CRUD instructions, and then data changes will be automatically sent to server and saved in the actual database. Whenever the server detects any data modifications, it will push the updated data to specific clients that subscribe to those data. This bi-directional data synchronization is accomplished automatically without any manual intervention. In order to create this magic, Meteor is using WebSocket to connect client and server under the hood so that any data changes on one end will be reflected to another instantly.

Build Automation Tool

Meteor not only takes care of server and web app applications, using Meteor’s build tool named Isobuild with the help of Cordova, a library that bundles HTML/JavaScript/CSS with native mobile functionalities, Meteor makes building iOS and Android apps a breeze. The generated mobile apps are hybrid apps that run JavaScript or show HTML pages inside a WebView. This workaround may compromise some user experience when compared to native mobile apps, but for many being able to manage it all under the same code base with web apps is quite a big selling point, and it saves a ton of development cost.

Overall, Meteor is a highly automated framework. This high level automation makes developers’ life much easier, yet it comes with a cost of jeopardized performance and scalability restrictions. As the user base grows, the automated data synchronization technique becomes the scaling chokepoint. To achieve the same capacity and performance as other hand-tuned backend technologies, Meteor usually consumes much more server hardware and bandwidth resources. So Meteor could be a great starting point and a perfect toolbox if one wants to prototype a project for all major platforms, but eventually at some point the system architecture has to be redesigned in a more professional way if the prototype becomes a production project with enough client base.

Sails.js: Superior MVC Framework for Node.js

Sails.js shares many similarities with Express. It’s a project generator, middleware and templating engine. It is in fact built on top of Express plus some higher level functionalities to speed up development.

MVC

Model View Controller

Sails.js adopts Model-View-Controller design pattern from its core. For those coming from Ruby on Rails or Laravel, they will find the structure for a Sails.js app all too familiar. Model represents data model that reflects database table/collection schema, View is HTML view with filled in data, Controller is where you put all server-side business logic in and acts as a glue between data and view.

Real-Time Communication

Not like an HTTP request where the client has to query for server data every time, or long polling connection which puts server in idling mode, Socket.io establishes a bidirectional event-based communication between client and server. Sails.js integrates Socket.io and wraps it up with some higher abstraction level API to provide more convenience, thus making Sails.js especially suitable for creating chat apps or multiplayer games.

Database ORM

Database ORM

Between backend logic and actual database manipulation, there is a middle ORM layer called Waterline. Simply put, this ORM tool provides a consistent syntax to access different databases without developers having to be concerned about varied database query languages, like SQL vs NoSQL, schema vs schema-less and so on.

Sails.js has an intermediate automation degree. It focuses on the server side logic and is production ready, and it provides a faster developing pace than Express without sacrificing any performance or future scalability. In particular for the large quantity of MVC pattern devotees, Sails.js has quite a smooth learning curve.

Wrap Up

This article sheds more light on some of the best Node.js frameworks. Rather than providing a Node.js framework performance comparison and ranking different Node.js frameworks, it lists the shining spots of each framework to stand out from the crowd so as to help Node.js developers pick up the most suited toolbox when building a project from the ground up.

So which Node.js back-end framework do you favor? Do you prefer some framework other than the ones we discussed above? Let us know in the comments section below.

Hire a Toptal expert on this topic.
Hire Now
Chuoxian Yang

Chuoxian Yang

Verified Expert in Engineering

Changsha, Hunan, China

Member since March 4, 2016

About the author

Chuoxian is a full-stack developer and tech company founder who has built multiple large-scale projects from blueprint to launch.

authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.

PREVIOUSLY AT

Blackthorn

World-class articles, delivered weekly.

By entering your email, you are agreeing to our privacy policy.

World-class articles, delivered weekly.

By entering your email, you are agreeing to our privacy policy.

Join the Toptal® community.