初識
由JS組成的技術棧不在需要環(huán)境切換了瘫俊!你再也不同從JS的思維切換到PHP鹊杖、C#、Ruby扛芽、Python...
JS只是個玩具嗎骂蓖?其實大多時候“不是游戲太差,只是玩家太爛”的緣故川尖。
Express 是精簡的登下、靈活的Node.js Web程序框架,為構建單頁叮喳、多頁被芳、混合Web應用提供了一系列健壯的功能特性。
- 精簡
框架開發(fā)者通常會忘記 “少即是多” 這一基本原則嘲更,Express的哲學是在你的想法和服務器之間充當薄薄的一層筐钟。這并不意味著它不夠健壯,或沒有足夠的有用特性赋朦,而是盡量少干預你篓冲,讓你充分表達自己的思想,同時提供一些有用的東西宠哄。
- 靈活
Express 哲學中另一個關鍵點是可擴展壹将。Express提供了一個非常精簡的框架,你可根據(jù)自己的需要添加或替換不能滿足你需要的部分毛嫉。這種做法很新鮮诽俯,因為只有在你需要的時候才會去添點東西。
- Web程序框架
Web程序除了網(wǎng)站承粤、網(wǎng)頁暴区,它還可向其他Web程序提供功能。程序是具有功能的辛臊,它不止是內(nèi)容的靜態(tài)集合仙粱。
- 單頁Web程序
單頁Web程序把整個網(wǎng)站(或很大部分)都下載到客戶端瀏覽器上,經(jīng)過初始下載后彻舰,用戶訪問不同頁面的速度更快了伐割,因為幾乎無需 與服務端通信。單頁程序的開發(fā)可使用 Angular或Ember等前端框架刃唤,Express跟他們都配合得很好隔心。
- 多頁和混合Web程序
多頁Web程序是更傳統(tǒng)的方式,網(wǎng)站上的每個頁面都是通過服務器發(fā)起單獨的請求得到的尚胞。這種方式確實比較傳統(tǒng)硬霍,單并不意味著它沒有優(yōu)點,只是現(xiàn)在有更多選擇了辐真。你可決定哪些內(nèi)容應該作為單頁程序提供须尚,哪些應該通過不同請求提供崖堤。混合說的就是同時使用者兩種方式的網(wǎng)站耐床。
簡史
Express締造者TJ Holowaychuk 說 Express 是在 Sinatra 的啟發(fā)下創(chuàng)建的密幔,Sinatra是一個基于Ruby的框架。Express借鑒了一個在Ruby上構建的框架并不奇怪撩轰,因為Ruby是一個在致力于讓Web開發(fā)變得更快胯甩、更高效、更可維護堪嫂、并衍生大量的Web開發(fā)方式偎箫。
除了Sinatra,Express跟Connect有著緊密的聯(lián)系皆串,Connect是一個Node的插件庫淹办。Connect創(chuàng)造了中間件(middleware)這個術語來描述插入式的Node模塊,它在不同程序上處理Web請求恶复。
Express4之前是捆綁Connect的怜森,Express4中Connect被去掉了,以便于中間件可各自獨立升級谤牡。
一種新型的Web服務器
Node是一種新型的Web服務器副硅,Node實現(xiàn)Web服務器的方式跟Express很像,非常精簡翅萤,其搭建和配置非常容易恐疲。Node和傳統(tǒng)服務器之間另一個主要區(qū)別在于:Node是單線程的。這是一種倒退嗎套么?事實證明這是天才之舉培己。
單線程極大地簡化了Web程序的編寫,如果你需要多線程程序的性能胚泌,僅需啟動更多地Node實例漱凝,即可得到多線程的線程優(yōu)勢。
通過服務器并行(性對于程序的并行)的多線程只是把復雜性轉移了诸迟,并沒有消除它啊愕乎?
盡管Node所用到Javascript引擎V8確實會將JS編譯為本地機器碼阵苇,但這一操作是透明的。所以從用戶角度來看感论,它表現(xiàn)的像純粹的解釋性語言一樣绅项。沒有單獨的編譯步驟,這減少了維護和部署的麻煩比肄。
生態(tài)系統(tǒng)
Node處于這個技術棧的核心位置快耿,由于構建一個功能性網(wǎng)站需要借助很多技術囊陡,因此衍生了一種用來描述網(wǎng)站架構基礎“技術棧”的縮略語掀亥。比如Linux撞反、Apache、MySQL搪花、PHP被稱為LAMP棧遏片。MongoDB的工程師Valeri Karpov發(fā)明了一個縮略語MEAN,指代的是Mongo撮竿、Express吮便、Angular、Node幢踏。
開始
Node所提供的范式跟傳統(tǒng)的Web服務器不同:你寫的程序就是Web服務器髓需。Node只是給你提供了一個構建Web服務器的框架。
vim http.js
var http = require('http');
// 事件驅(qū)動編程房蝉,HTTP請求就是要處理的事件僚匆。
http.createServer(function(req,res){
// 內(nèi)容類型設置為普通文本,并發(fā)送字符串
res.writeHead(200, {'Content-Type':'text/plain'});
res.end('Hello world!');
}).listen(3000);
console.log('server started on localhost:3000');
node http.js
事件驅(qū)動編程惨驶,http.js中事件是隱含的:HTTP請求就是要處理的事件白热,http.createServer()將函數(shù)作為一個參數(shù),每次有HTTP請求發(fā)送過來就會調(diào)用該函數(shù)粗卜。這里這是把內(nèi)容類型設置為普通文本屋确,并發(fā)送字符串。
vim http2.js
var http = require('http');
// 事件驅(qū)動編程续扔,HTTP請求就是要處理的事件攻臀。
http.createServer(function(req,res){
// 規(guī)范化URL,去除查詢字符串纱昧、可選反斜杠后轉為小寫刨啸。
var path = req.ur.replace(/\/?(?:\?.*)?$/, '').toLowerCase();
switch(path){
case '':
res.writeHead(200,{'Content-Type':'text/plain'};
res.end('homepage');
break;
case '/about':
res.writeHead(200,{'Content-Type':'text/plain'};
res.end('about');
break;
default:
res.writeHead(404,{'Content-Type':'text/plain'};
res.end('Not Found');
break;
}
}).listen(3000);
console.log('server started on localhost:3000');
node http.js
省時省力
腳手架
腳手架并不是一個新想法,多數(shù)人通過Ruby才接觸大這個概念识脆。這個想法很簡單设联,大多數(shù)項目都需要一定數(shù)量的套路化代碼,誰會想每次開始新項目時都重新寫一次呢灼捂?簡答的方式是創(chuàng)建一個通用的項目骨架离例,每次開始新項目時,僅需復制骨架或模板悉稠。
RoR將此概念向前推進了一步宫蛆,它提供了一個可自動生成腳手架的程序。Express借鑒了RoR的這一做法的猛,提供了一個生成腳手架的工具耀盗,從而讓你開始一個新的Express項目想虎。
# 安裝express
npm install -g express
# 安裝腳手架
npm install -g express-generator
# 卸載express
npm uninstall -g express
npm uninstall -g express-generator
# 進入項目目錄創(chuàng)建應用
express app
cd app & npm install
# 安裝服務器監(jiān)聽工具
npm install -g supervisor
supervisor bin/www
Express是如何工作的呢?
Express是單入口的主文件啟動叛拷,在Node命令中可啟動舌厨,它也會以模塊的形式存在。
主文件會做些什么事情呢胡诗?
- 引入模塊
- 配置Express
- 連接數(shù)據(jù)庫
- 定義中間件
- 定義路由
- 啟動應用
- 以模塊形式輸出應用
當前Express的應用運行起來后便開始監(jiān)聽其你去邓线,每個剛來的請求都會根據(jù)規(guī)定的中間件和路由鏈自上而下處理』突郑控制好執(zhí)行流程是非常重要的骇陈,例如在文件中上游中的路由或中間件比下游更具優(yōu)先權。
那么瑰抵,中間件是什么呢你雌?因為可以在每個HTTP請求過程中添加多個函數(shù)來對其進行處理,所以稱這些函數(shù)為中間件二汛。
中間件能干些什么呢婿崭?
- 解析cookie中的信息并將其填入req對象中,供后續(xù)的中間件或路由使用肴颊。
- 解析URL中的參數(shù)并填入req對象供后續(xù)中間件或路由使用
- 若用戶已認證即擁有cookie或session氓栈,可根據(jù)他們中參數(shù)的值從數(shù)據(jù)庫獲得響應,并填入req對象供后續(xù)中間件或路由使用婿着。
- 認證或取消認證用戶或請求
- 呈現(xiàn)數(shù)據(jù)并終止響應
Express的核心是中間件
//聲明中間件
var cookieParse = require('cookie-parser');//解析HTTP請求中的cookie數(shù)據(jù)(req.cookie)
var bodyParse = require('body-parser');//解析HTTP請求的body數(shù)據(jù)(req.body)
//使用中間件
app.use(cookieParser());
app.use(bodyParse.json());
中間件能夠?qū)φ埱笞龀鲇杏玫氖虑槭谑荩蛱峁椭莫毩?zhí)行函數(shù)。中間件內(nèi)部包含一連串的函數(shù)竟宋,這些函數(shù)都會對經(jīng)過它的請求進行不同的處理提完。
自己編寫中間件很簡單
app.use(function(req, res, next){
if(req.query.id){
//todo
}else if(req.body.name){
//todo
}else{
//todo
}
next();
})
Express中的路由
app.use('/', routes);
app.use('/users', users);
路由是不區(qū)分大小寫,默認情況下Express禁止開發(fā)人員以字符串查詢參數(shù)的形式請求路由丘侠。
GET:www.junchow.com/?id=1
數(shù)據(jù)提交方式
- 傳統(tǒng)服務端提交方式
被認為是傳統(tǒng)搜索引擎的最佳方式徒欣,但會讓用戶(尤其是移動端)等待更久,而且不流暢蜗字。 - REST API/AJAX 提交方式
通過REST API或HTTP請求發(fā)送或接收打肝,在客戶端渲染HTML的方式。被眾多前端框架采用挪捕,因為它能更好地提高效率和組織代碼闯睹,因為HTML只需要在客戶端進行渲染,傳輸中只包含數(shù)據(jù)担神。