NodeJs框架对比:Express、Koa、Hapi

Stella981
• 阅读 910

https://www.airpair.com/node.js/posts/nodejs-framework-comparison-express-koa-hapi

1 Introduction

Express.js is the most popular Node.js web application framework used today. It seems to be the base dependency in most Node.js web applications, even some popular frameworks like Sails.js are built off of Express. However there are more options available that have the same "sinatra-like" feel to them. The next two most popular frameworks are Koa and Hapi respectively.

This is not going to persuade you to use one framework over the other, it's merely going to help you get a better understanding of what each framework can do and where one might trump the other.

2 Framework backgrounds

All three of the frameworks we will be looking at have a lot in common. All can create a server with just a few lines of code and all make creating a REST API very simple. Lets look at how these frameworks began.

2.1 Express

The initial commit for Express was made on June 26, 2009 by TJ Holowaychuk and 660 commits later version 0.0.1 was released on January 2, 2010. The two main contributors at that time were TJ and Ciaron Jessup. At the time of the first release the framework was described as per the readme.md on github

Insanely fast (and small) server-side JavaScript web development framework built onnode.js and V8 JavaScript engine.

Fast forward almost 5 years and 4,925 commits, now 4.10.1 is the latest version maintained by StrongLoop as TJ is now concentrating in the Go-Lang community.

2.2 Koa

The initial commit for Koa was just over a year ago on August 17, 2013 by none other than TJ Holowaychuk. He describes it as "Expressive middleware for node.js using generators via co to make writing web applications and REST APIs more enjoyable to write". Koa is advertised as having a small footprint of ~400 SLOC. It is now on version 0.13.0 with 585 commits.

2.3 Hapi

The initial commit for Hapi was on August 5, 2011 by Eran Hammer a member of WalmartLabs. Hapi was created by parts of Postmile and was originally built on top of Express. Later it was developed into its own framework because of what Erin state's in his blog:

hapi was created around the idea that configuration is better than code, thatbusiness logic must be isolated from the transport layer...

3,816 commits later Hapi is is on version 7.2.0 and is still maintained by Eran Hammer.

Finally lets look at some community statistics to see how popular these frameworks are:

Metric

Express.js

Koa.js

Hapi.js

Github Stars

16,158

4,846

3,283

Contributors

163

49

95

Packages that depend on:

3,828

99

102

StackOverflow Questions

11,419

72

82

3 Creating a server

The first step for any developer when working on a Node.js web application is to create a basic server. So lets create a server using each framework to see their similarities and differences.

3.1 Express

var express = require('express'); var app = express(); var server = app.listen(3000, function() { console.log('Express is listening to http://localhost:3000'); }); 

Get expert  javascript help

This is probably pretty natural to all node developers. We require express and then instantiate it by assigning it to the variable app. Then instantiate a server to listen to a port, port 3000. The app.listen() is actually just a wrapper around node'shttp.createServer().

3.2 Koa

var koa = require('koa'); var app = koa(); var server = app.listen(3000, function() { console.log('Koa is listening to http://localhost:3000'); }); 

Get expert  javascript help

Right away you can see that Koa is similar to Express. Essentally you just required koa instead of express. Also app.listen() is the exact same wrapper function as used in Express.

3.3 Hapi

var Hapi = require('hapi'); var server = new Hapi.Server(3000); server.start(function() { console.log('Hapi is listening to http://localhost:3000'); }); 

Get expert  javascript help

Hapi is the unique one of the group. First like always, hapi is required but instead of instantiating a hapi app, you create a new Server and specify the port. In Express and Koa we get a callback function but in Hapi we get a new server object. Then once we call server.start() we start the server on port 3000 which then returns a callback. However this is not like Koa and Express, it is not a wrapper aroundhttp.CreateServer(), it is using it's own logic.

4 Routes

Now lets dig into one of the most important features of a server, routing. First lets create the cliche "Hello world" application for each framework and then move on to something a little more useful, REST API.

4.1 Hello world

4.1.1 Express

var express = require('express'); var app = express(); app.get('/', function(req, res) { res.send('Hello world'); }); var server = app.listen(3000, function() { console.log('Express is listening to http://localhost:3000'); }); 

Get expert  javascript help

We are using the get() method to catch the incoming request of "GET /" and then invoke a callback function that handles two parameters req and res. For this example we are only utilizing res to return back to the page a string usingres.send(). Express has a variety of built in methods that are used to handle the routing functionality. The following are some of the more commonly used methods that are supported by Express (but not all of the methods): get, post, put, head,delete...

4.1.2 Koa

var koa = require('koa'); var app = koa(); app.use(function *() { this.body = 'Hello world'; }); var server = app.listen(3000, function() { console.log('Koa is listening to http://localhost:3000'); }); 

Get expert  javascript help

Koa is slightly different than Express, it is using ES6 generators. Any function preceded by a * means the function will return a generator object. Basically these generators yield values synchronously but that is beyond the scope of this post. Within the app.use() the generator function sets the response body. In Koa theContext which is equivalent to the this identifier is an encapsulation of node'srequest and response objects. this.body is a method in the Koa Responseobject. this.body can be set to a string, buffer, stream, object, or null. This example we used one of the few middlewares provided in the Koa core. This middleware we used catches all routes and responds with the string provided.

4.1.3 Hapi

var Hapi = require('hapi'); var server = new Hapi.Server(3000); server.route({ method: 'GET', path: '/', handler: function(request, reply) { reply('Hello world'); } }); server.start(function() { console.log('Hapi is listening to http://localhost:3000'); }); 

Get expert  javascript help

Here we are using the built in method that the server object provides usserver.route() which has the following options: path(required), method(required),vhost, and handler(required). The HTTP method can handle the typical requestsGET, PUT, POST, DELETE, and * which catches any route. The handler is passed a reference to the request object and must call reply with the containing payload. The payload can be a string, a buffer, a serializable object, or a stream.

4.2 REST API

The Hello world never really does much except show the most basic/simplest way to get an application up and running. REST APIs are almost a must in all data heavy applications and will help better understand how these frameworks can be used. So let's take a look at how each handles REST APIs.

4.2.1 Express

var express = require('express'); var app = express(); var router = express.Router(); // REST API router.route('/items') .get(function(req, res, next) { res.send('Get'); }) .post(function(req, res, next) { res.send('Post'); }); router.route('/items/:id') .get(function(req, res, next) { res.send('Get id: ' + req.params.id); }) .put(function(req, res, next) { res.send('Put id: ' + req.params.id); }) .delete(function(req, res, next) { res.send('Delete id: ' + req.params.id); }); app.use('/api', router); // index app.get('/', function(req, res) { res.send('Hello world'); }); var server = app.listen(3000, function() { console.log('Express is listening to http://localhost:3000'); }); 

Get expert  javascript help

So we added our REST API to our existing Hello World application. Express offers a little shorthand for handling routes. This is Express 4.x syntax but it is essentially the same in Express 3.x except you don't need the express.Router() and you will not be able to use the line app.use('/api', router). Instead you will replace therouter.route()'s with app.route() while prepending the existing verb with /api. This is a nice approach because it reduces the chance of developer errors and minimizes the places to change the HTTP method verbs.

4.2.2 Koa

var koa = require('koa'); var route = require('koa-route'); var app = koa(); // REST API app.use(route.get('/api/items', function*() { this.body = 'Get'; })); app.use(route.get('/api/items/:id', function*(id) { this.body = 'Get id: ' + id; })); app.use(route.post('/api/items', function*() { this.body = 'Post'; })); app.use(route.put('/api/items/:id', function*(id) { this.body = 'Put id: ' + id; })); app.use(route.delete('/api/items/:id', function*(id) { this.body = 'Delete id: ' + id; })); // all other routes app.use(function *() { this.body = 'Hello world'; }); var server = app.listen(3000, function() { console.log('Koa is listening to http://localhost:3000'); }); 

Get expert  javascript help

It's pretty obvious that Koa doesn't have the ability to reduce the repetitive route verbs like Express. It also requires a separate middleware to handle routes. I chose to use koa-route because it is maintained by the Koa team but there are a lot of routes available to use by other maintainers. The routes are very similar to Express with using the same keywords for their method calls like .get(), .put(), .post(), and.delete(). One advantage Koa has with handling its routes, is that it is using the ES6 generator functions which helps reduce the handling of callbacks.

4.2.3 Hapi

var Hapi = require('hapi'); var server = new Hapi.Server(3000); server.route([ { method: 'GET', path: '/api/items', handler: function(request, reply) { reply('Get item id'); } }, { method: 'GET', path: '/api/items/{id}', handler: function(request, reply) { reply('Get item id: ' + request.params.id); } }, { method: 'POST', path: '/api/items', handler: function(request, reply) { reply('Post item'); } }, { method: 'PUT', path: '/api/items/{id}', handler: function(request, reply) { reply('Put item id: ' + request.params.id); } }, { method: 'DELETE', path: '/api/items/{id}', handler: function(request, reply) { reply('Delete item id: ' + request.params.id); } }, { method: 'GET', path: '/', handler: function(request, reply) { reply('Hello world'); } } ]); server.start(function() { console.log('Hapi is listening to http://localhost:3000'); }); 

Get expert  javascript help

First impressions of the routes in Hapi are how clean and readable they are compaired to the other frameworks. Even the required options method, path,handler, and replay for the routes are easy to the eye. Like Koa, there is a lot of reuse of code making the room for error larger. However this is intention, Hapi is more concerned about configuration and wants the code to be cleaner for easier use in a team. Hapi also wanted to improve error handling which it does without any code being written on the developers end. If you try to hit a route not described in the REST API it will return a JSON object with a status code and error description.

5 The Good and The Bad

5.1 Express

5.1.1 The Good

Express has the biggest community not only out of the three frameworks compared here but out of all the web application frameworks for Node.js. It is the most matured framework out of the three, with almost 5 years of development behind it and now has StrongLoop taking control of the repository. It offers a simple way to get a server up and running and promotes code reuse with it's built in router.

5.1.2 The Bad

There is a lot of manual tedious tasks involved in Express. There is no built in error handling, it is easy to get lost in all of the middleware that could be added to solve a solution, and there are many ways to do one thing. Express describes itself as being opinionated, this could be good or bad but for beginning developers who must likely chose Express, this is a bad thing. Express also has a larger foot print compared to the other frameworks.

5.2 Koa

5.2.1 The Good

Koa has a small footprint, it is more expressive and it makes writing middleware a lot easier than the other frameworks. Koa is basically a barebone framework where the developer can pick (or write) the middleware they want to use rather than compromising to the middleware that comes with Express or Hapi. It's the only framework embracing ES6, for instance its using ES6 generators.

5.2.2 The Bad

Koa is still unstable and heavily in development. Using ES6 is still ahead of the game for example version 0.11.9+ of Node.js needs to be used to run Koa and right now the latest stable version on Node.js is version 0.10.33. One thing that is in the good but could also be in the bad much like Express is the option of selecting multiple middlewares or writing your own middleware. Such as the router we looked at earlier, there are a lot of middleware routers to handle a variety of options.

5.3 Hapi

5.3.1 The Good

Hapi is proud to say that their framework is based on configuration over code, and a lot of developers would argue that this is a good thing. This is very usual in large teams to add consistency and reusability. Also with the framework being backed by WalmartLabs as well as many other big name companies using Hapi in production, it has been battle tested and companies are confident enough to run their applications off of it. So all signs point towards this project continuing to mature in to a great framework.

5.3.2 The Bad

Hapi definitely seems to be more tailored towards bigger or more complex applications. It is probably a little too much boilerplate code to throw together a simple web app and there is also a lot less examples or open source applications that use hapi. So choosing it might involve a little more part on the developer rather than using third party middleware.

6 Summary

We have seen some good but practical examples of all three frameworks. Express is definitely the most popular and most recognized framework of the three. It is almost a reaction to first create a server using Express when starting new development on an application but hopefully now there might be some thought involved whether to use Koa or Hapi as an alternative. Koa shows real promise for the future and is ahead of the pack with embracing ES6 and the web component ideology that the web development community is moving towards. Hapi should be the first consideration for large teams and large projects. It pushes for configuration over code which almost always benefits teams and the re-usability most teams strive towards. Now go out and try a new framework, maybe you'll love it, maybe you'll hate, but you will never know and in the end, it will make you a better developer.

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这