小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

[譯]Node.js框架對比:Express/Koa/Hapi

 WindySky 2017-05-19

本文翻譯自: 

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

  

1、介紹

  直至今日,Express.js仍然是最為流行的Node.js Web應(yīng)用程序框架。它似乎已經(jīng)逐漸成為大多數(shù)Node.js Web應(yīng)用程序的基礎(chǔ)依賴框架,包括很多流行的框架,比如Sail.js就是以Express.js為基礎(chǔ)搭建的。然而現(xiàn)在我們有了更多“類sinatra”(注:sinatra是一款Ruby框架,代碼非常簡潔,號稱開發(fā)一個博客項(xiàng)目只需要100行代碼)似的框架可以選擇。也就是接下來我們將分別介紹的Koa和Hapi兩個框架。

 

  本文的目的并不是打算去說服大家去使用其中的任何一款框架,而是希望能夠幫助大家去對比分析這三個框架的優(yōu)劣勢。

  

2、框架背景

 

  今天我們對比的這三款框架其實(shí)都有很多的共通點(diǎn)。比如他們都可以幾行代碼就能創(chuàng)建一個服務(wù),而且進(jìn)行REST API的開發(fā)也是小菜一碟。下面我們就分別來看這三款框架吧。

 

2.1、Express

 

  2009年6月26日,TJ Holowaychuk 第一次提交了Express的代碼。在2010年1月2日,Express正式發(fā)布了0.0.1版本,截止當(dāng)時,作者已經(jīng)提交了超過660次代碼。當(dāng)時Express的兩位主要開發(fā)維護(hù)者分別是TJ 以及 Ciaron Jessup。第一版發(fā)布的時候,Express在Github的readme.md介紹文件中式這么描述這塊框架的:

一款基于node.js以及Chrome V8引擎,快速、極簡的JS服務(wù)端開發(fā)框架。 

  5年多后今天,Express目前已經(jīng)發(fā)布到4.10.1版本,提交超過4925次代碼,目前主要是采用StrongLoop進(jìn)行開發(fā)維護(hù),因?yàn)門J同學(xué)已經(jīng)轉(zhuǎn)入GO語言開發(fā)社區(qū)了。

 

2.2、Koa

  Koa是在一年以前也就是在2013年8月17日由TJ同學(xué)(是的,還是他...)首次提交的代碼。他當(dāng)時是這么描述Koa的:“更具有表現(xiàn)力,更健壯的Node.js中間件。基于co組件的generators處理異步回調(diào),無論是Web應(yīng)用還是REST API開發(fā),你的代碼都將變得更加優(yōu)雅”。(注:Koa2發(fā)布后,已經(jīng)放棄了引入co組件,而是開始采用ES7的async/await語法處理異步回調(diào))。輕量化的Koa號稱不超過400行代碼。(注:SLOC是源代碼行數(shù),又分為物理代碼行數(shù)LOC,以及邏輯代碼行數(shù)LLOC)。截止目前,Koa已經(jīng)發(fā)布了0.13.0版本,超過585次的代碼提交。

 

2.3、Hapi

  Hapi是由來自于沃爾瑪實(shí)驗(yàn)室的Eran Hammer同學(xué)在2011年8月5日首次提交的。原本他只是Postmile(這是一款在node.js上開發(fā)的協(xié)作列表工具,服務(wù)端由Hapi完成的一個核心部件,同樣也是基于Express開發(fā)。后來Hapi才被獨(dú)立出來作為一款框架進(jìn)行開發(fā)維護(hù),Eran同學(xué)在他的博客里這樣說道:

  “Hapi的核心思想是配置優(yōu)于代碼,所以業(yè)務(wù)代碼必須從傳輸層中剝離出來”

  至今為止,Hapi已經(jīng)提交超過3816次代碼,版本是7.2.0,當(dāng)前仍然是由Eran Hammer進(jìn)行主要開發(fā)維護(hù)。

 

  OK,最后讓我們來通過社區(qū)的統(tǒng)計(jì)數(shù)據(jù)來看看這三個框架的活躍程度:

  

參考項(xiàng)

Express.js

Koa.js

Hapi.js

Github點(diǎn)贊數(shù)

16158

5846

3283

代碼貢獻(xiàn)者

163

49

95

依賴包數(shù)量

3828

99

102

StackOverFlow提問數(shù)

11419

72

82

 

3、創(chuàng)建服務(wù) 

  基本上每個剛開始接觸Node.js的開發(fā)者第一步操作就是創(chuàng)建一個服務(wù)。因?yàn)橄旅嫖覀儗⒁来问褂妹總€框架來分別創(chuàng)建一個服務(wù),來看看他們之間的相似處與不同的地方。

 

3.1、Express 

復(fù)制代碼
var express = require('express');
var app = express();

var server = app.listen(3000, function() {
    console.log('Express is listening to http://localhost:3000');
});
復(fù)制代碼

 

 

  上面的操作對于大多數(shù)Node開發(fā)者來說應(yīng)該都是很熟練了。我們先引入express,然后創(chuàng)建一個實(shí)例對象并將其賦值給變量app。接下來是實(shí)例化一個服務(wù),并且開始監(jiān)聽3000端口。app.listen() 其實(shí)就是對nodejs原生的http.createServer()進(jìn)行了一層封裝。

 

3.2、Koa 

復(fù)制代碼
var koa = require('koa');
var app = koa();

var server = app.listen(3000, function() {
    console.log('Koa is listening to http://localhost:3000');
}); 
復(fù)制代碼

  顯而易見,Koa的語法和Express非常相似。其實(shí)來說你只需要將引入express修改為引入koa即可。同樣的,app.listen() 也是對http.createServer()進(jìn)行了一層封裝。

 

3.3、Hapi 

 

復(fù)制代碼
var Hapi = require('hapi');
var server = new Hapi.Server(3000);

server.start(function() {
    console.log('Hapi is listening to http://localhost:3000');
});
復(fù)制代碼

 

  Hapi的語法比較特別一些。不過,第一步還是引入hapi,但是這里是實(shí)例化存入一個hapi app變量中,然后就可以創(chuàng)建一個指定端口的服務(wù)了。在Express和Koa中這一步我們得到的是一個回調(diào)函數(shù),但是Hapi返回的是一個server對象。一旦我們通過server.start()來調(diào)用這個在3000端口的服務(wù)以后,他將會返回一個回調(diào)函數(shù)。然后跟Koa和Express不一樣的地方在于,這個回調(diào)并不是對http.CreateServer()進(jìn)行的一層封裝,而是Hapi自己實(shí)現(xiàn)的邏輯。

 

4、路由

  接下來我們繼續(xù)深入了解作為一個服務(wù)的一個重要功能,那就是路由。第一步我們將使用每個框架來分別創(chuàng)建一個“Hello World”應(yīng)用,然后再繼續(xù)關(guān)注一些更實(shí)用的功能,REST API。

 

4.1 Hello World

 

4.1.1  Express

復(fù)制代碼
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');
});
復(fù)制代碼

 

  我們使用get()方法來捕獲“GET /”請求,然后調(diào)用一個回調(diào)函數(shù)來處理請求,該回調(diào)函數(shù)擁有兩個參數(shù):req與res。在這個例子中我們僅僅使用了res的res.send()方法來向頁面返回一個字符串。Express包含了很多內(nèi)置的方法來處理路由功能。下面是幾個Express中常用的方法(只是部分,并不是全部方法):get, post, put, head, delete…

 

4.1.2 Koa 

復(fù)制代碼
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');
});
復(fù)制代碼

  Koa和Express有些許的不同之處,因?yàn)樗褂昧薊S6 的generators語法。(注:generators是ES6提出的一種異步回調(diào)的解決方法,在ES7中將直接升級為async/await)在方法前面加上一個 * 表示該方法返回一個generator對象。generators函數(shù)的作用就是使得異步函數(shù)產(chǎn)生一些同步的值,但是這些值仍然是在當(dāng)前的請求范圍之類。(注:generator對通過yield 定義不同的狀態(tài)值,return也算是一個狀態(tài)值。詳情了解:http://es6./#docs/generator在app.use()中,generator函數(shù)對響應(yīng)體進(jìn)行賦值。在Koa中this對象,其實(shí)就是對node的request與response對象進(jìn)行的封裝。this.body在Koa中是一個響應(yīng)體對象的方法。它基本上能被賦值為任何值,字符串、buffer、數(shù)據(jù)流、對象或者是null。Koa核心庫提供了很多中間件,這里我們只是使用了其中的一個,這個中間件可以捕獲所有的路由,然后響應(yīng)一個字符串。

 

4.1.3 Hapi

復(fù)制代碼
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');
});
復(fù)制代碼

  這里我們使用了由server對象提供的一個內(nèi)置方法:server.route(),這個方法需要這些參數(shù):path(必填)、method(必填)、vhost以及handler(必填)。這個HTTP方法可以處理我們常見的GET/PUT/POST/DELETE請求,也可以使用*來處理所有路由請求?;卣{(diào)函數(shù)會被Hapi默認(rèn)傳入request對象以及reply方法,reply是必須被執(zhí)行的方法,而且需要傳入一項(xiàng)數(shù)據(jù),這個數(shù)據(jù)可以是字符串、序列化的對象或者流。

  

4.2 REST API

  Hello World程序從來都沒有太多的期望,因?yàn)樗荒苷故緞?chuàng)建及運(yùn)行一個應(yīng)用最基本最簡單的操作。REST API幾乎是所有大型應(yīng)用程序所必須的一個功能,同時對于我們更好的理解這些框架有很大的幫助。因此接下來我們將看看這幾個框架是如何來處理REST API。

 

4.2.1 Express  

復(fù)制代碼
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');
});
復(fù)制代碼

  我們在現(xiàn)有的Hello World程序上增加了REST API。Express提供了一些縮寫的方法來處理路由。這是Express 4.x 版本的語法,其實(shí)跟Express 3.x 版本差不多,同樣希望你不再使用express.Router()方法,而是換成新的API:app.use('/api', router)。新的API可以讓我們使用app.route()來替換之前的router.route(),當(dāng)然了需要添加一個描述性的動詞/api.這是一個不錯的修改,因?yàn)榻档烷_發(fā)者出現(xiàn)錯誤的機(jī)會,同時對原有的HTTP方法進(jìn)行了最小的一個修改。

 

4.2.2 Koa    

復(fù)制代碼
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');
}); 
復(fù)制代碼

  很明顯,Koa并不能像Express那樣去降低route動詞的重復(fù)性。它同時還需要引入一個獨(dú)立的中間件來處理路由。我選擇使用koa-route,是因?yàn)樗饕怯蒏oa小組來開發(fā)維護(hù),當(dāng)然也還有很多其他開發(fā)者貢獻(xiàn)的路由中間件可以選擇。從方法名的關(guān)鍵字上來看,koa的路由和express也是非常相似的,例如.get(), .put(), .post(), 以及 .delete()。

  Koa在處理路由有一個優(yōu)勢,它使用了ES6 的generator函數(shù),從而降低了回調(diào)函數(shù)的復(fù)雜度。

 

4.2.3  Hapi   

復(fù)制代碼
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');
});
復(fù)制代碼

   跟其他框架相比,Hapi的路由配置給人的第一印象就是代碼清爽,可讀性高。甚至連必填的配置參數(shù)method,path,hanlder以及reply都非常容易辨別。跟Koa一樣,Hapi路由的代碼重復(fù)性也比較高,所以出錯的幾率也比較大。之所有這么做,是因?yàn)镠api更希望使用配置來完成路由,這樣我們的代碼會更清爽,在小組內(nèi)也會更容易的維護(hù)。Hapi同樣試圖去提高代碼錯誤處理能力,因?yàn)橛械臅r候他甚至不需要開發(fā)者編寫任何代碼(注:意思是完全都過配置實(shí)現(xiàn),回調(diào)函數(shù)也是用默認(rèn)的。這樣出錯的 概率就了很多,也更容易上手)。如果你試圖去訪問一個沒有在REST API中定義的路由,那么Hapi將會返回一個包含狀態(tài)值與錯誤信息的JSON對象。

  

5、優(yōu)劣勢 

 

5.1 Express

 

5.1.1 優(yōu)勢

  Express擁有最大社區(qū),比僅僅是跟這三個框架相比,而是對于所有的Nodejs框架來說也是最大的。目前來說,他是最為三者中最為成熟的框架,接近5年的開發(fā)投入,同時還采用了StrongLoop(注:StrongLoop是一個進(jìn)程管理工具,提供CLI與UI界面。)對線上倉庫的代碼進(jìn)行管理。他提供了一種簡單的方式來創(chuàng)建和運(yùn)行一個服務(wù),同時路由的內(nèi)置也使得代碼得到了重復(fù)使用。

 

5.1.2 劣勢

  在使用Express過程中,我們往往要處理很多單調(diào)乏味的任務(wù)。比如他沒有內(nèi)置的錯誤處理機(jī)制,另外對于同樣一個問題可以有很多中間件來供選擇,這也使得開發(fā)者容易迷失在中間件的選擇中,總而言之就是,一個問題你會有N多解決方案。Express聲稱自己是可配置選擇的,這其實(shí)不沒有好或不好,但是對于一個剛剛接觸Express的開發(fā)者來說,這就是他的劣勢了。另外,Express跟其他的框架相比也還有很大的差距。

  

5.2 Koa

 

5.2.1 優(yōu)勢

  Koa的一個小進(jìn)步就是他的代碼比較富有表現(xiàn)力,開發(fā)中間件也比其他框架更容易得多。Koa是一個很基礎(chǔ)的準(zhǔn)系統(tǒng)框架,開發(fā)者可以選擇(或開發(fā))他們所需要的中間件,而不是去選擇Express或Hapi的中間件。他同時也是三者中唯一一個積極擁抱ES6的框架,比如采用了ES6 generators函數(shù)。

 

5.2.2 劣勢 

  目前Koa還處于不穩(wěn)定版本,還處在開發(fā)階段。使用ES6進(jìn)行開發(fā)的確是處于領(lǐng)先水平,比如Koa需要基于Nodejs 0.11.9以上的版本運(yùn)行,而目前nodejs的文本版本是0.10.33。這是一件可以算作好也可以算作不好的事情,就像Express開發(fā)者有很多中間件要選擇甚至自己開發(fā)中間件一樣。比如我們在上面看到的一樣,對于路由來說就有很多中間件供我們選擇。

  

5.3 Hapi

 

5.3.1 優(yōu)勢

   Hapi一直很自豪的說他們的框架是配置優(yōu)于代碼,當(dāng)然也有很多開發(fā)者可能會質(zhì)疑把這一點(diǎn)算作是優(yōu)勢。但這一點(diǎn)對于大型項(xiàng)目組來說,的確是可以保持代碼的統(tǒng)一性以及代碼復(fù)用性。另外這款框架是由沃爾瑪實(shí)驗(yàn)室支持的,也有很多大公司在線上環(huán)境使用Hapi,表明他已經(jīng)通過了嚴(yán)峻的測試,因?yàn)檫@些公司會考慮得更多才會使用Hapi來運(yùn)行他們的項(xiàng)目。因此所有的這些跡象都表明Hapi正在朝一個偉大的框架發(fā)展。

  

5.3.2 劣勢

   Hapi的定位更傾向于大型或復(fù)雜的應(yīng)用程序。對于一個簡單的應(yīng)用來說,Hapi在代碼上反而有些顯得冗余了,另外目前Hapi所提供的樣例程序也比較少,使用Hapi進(jìn)行開發(fā)的開源應(yīng)用同樣很少。因此,如果選擇Hapi的話,你可能要投入更多精力進(jìn)行開發(fā),而不是簡單的調(diào)用一個第三方中間件。

 

6、總結(jié)

   我們已經(jīng)看了三個框架還算不錯具有代表性的一些樣例代碼。Express仍然是當(dāng)下最為流行,以及最被人所知曉的框架。當(dāng)開始一個新的開發(fā)項(xiàng)目時,可能大家的第一反應(yīng)就是用Express來創(chuàng)建一個服務(wù)。但是現(xiàn)在更希望大家多考慮考慮使用Koa或者Hapi。Koa積極擁抱ES6的語法,展示了promise的真正魅力。目前整個web開發(fā)社區(qū)也都意識到ES6的優(yōu)勢,正在逐步往上面遷移。Hapi應(yīng)該是大型項(xiàng)目組或者大型項(xiàng)目的第一選擇。他所倡導(dǎo)的配置優(yōu)于代碼會使得項(xiàng)目組 在代碼的重復(fù)性上受益不淺,這也正是大多數(shù)項(xiàng)目組所追求的目標(biāo)?,F(xiàn)在行動起來,嘗試一款新的框架吧,可能你會喜歡他也可能會討厭他,但如果不去嘗試你永遠(yuǎn)也不會知道結(jié)果是什么,最終所有的這些經(jīng)歷都會讓你成長為一個更加優(yōu)秀的開發(fā)者。

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多