Express
最近一個多月在用Express+MySQL寫公司內(nèi)部業(yè)務(wù)(商品訂單數(shù)據(jù)分析)的一些簡單的邏輯,天天整SQL,搞定時任務(wù),搞日志,搞AntV F2+Vue,結(jié)果年前要重構(gòu)項目,全部從0開始,包括后臺數(shù)據(jù)庫建表.....
最近想抽空看了下Node與Express開發(fā),記錄一點筆記,個人感覺還是看文檔比較好

招個前端,讓他負責點后端,維護哈服務(wù)器,
然后拍攝一下產(chǎn)品,拍個產(chǎn)品視頻,做一下圖,
再幫忙做下銷售,
隨便給公司員工炒幾個菜,
再刷兩間廁所,
就在那兒喊苦了,哎,現(xiàn)在的年輕人啊

就當鞏固下知識吧,接觸Express蠻久了,年中搭了一個小站點,采用Express+art-template做頁面渲染,客戶端部分功能使用vue.js庫(jQuery 寫邏輯的代碼量太大了),中轉(zhuǎn)后臺接口渲染模板頁,坑就是 vue 和 art-template 的兩種模板語法之一{{}}會沖突,需要單獨修改源碼設(shè)置
你可能會問,為啥不用Koa2,Egg.js,ThinkJS,sails........,我是挺想用Koa或者egg的,想了一番,我還是先把ES6搞明白吧....(滑稽臉) 年底還要整支付寶和微信小程序...

官網(wǎng)是這么介紹的,精簡的、靈活的 Node.js Web 程序框架,為構(gòu)建單頁、多頁及混合的 Web 程序提供了一系列健壯的功能特性
- 精簡: Express 的哲學(xué)是在你的想法和服務(wù)器之間充當薄薄的一層,這并不意味著它不夠健壯,或者沒有足夠的有用特性,而是盡量少干預(yù)你,讓你充分表達自己的思想,同時提供一些有用的東西
- 靈活: Express 哲學(xué)中的另一個關(guān)鍵點是可擴展
- Web 程序框架: 網(wǎng)站是 Web 程序,網(wǎng)頁也是 Web 程序
- 單頁 Web 程序
- 多頁和混合的 Web 程序:多頁 Web 程序是更傳統(tǒng)的方式。網(wǎng)站上的每個頁面都是通過向服務(wù)器發(fā)起單獨的請求得到的
Express4.0
- Connect ? 已經(jīng)從 Express 中去掉了,所以除了 static 中間件,你需要自己安裝相應(yīng)的開發(fā)包(即 connect ),與此同時,Connect 將一些中間件移到了它自己的包內(nèi)
- body-parser ? 現(xiàn)在有自己的包了,它不再包含 multipart 中間件,因而也關(guān)閉了一個重大的安全漏洞?,F(xiàn)在可以放心使用 body-parser 中間件了
- 不必再將 Express router 鏈接到程序里。所以應(yīng)該從已有的 Express 3.0 中去掉 ? app.use(app.router)
- app.configure ? 被去掉了,只要檢查 app.get(env) (用 switch 或 if 語句)就可以取代該方法。
使用終端
很多工具都有 GUI 界面,所以如果你確實不想使用終端,你有自己的選擇權(quán),但你就只能靠自己去學(xué)習(xí)了
Console2(http://sourceforge.net/projects/console/)或
ConEmu(https://github.com/Maximus5/ConEmu)
這些更精致的控制臺,以及微軟自己的 PowerShell,技藝嫻熟的 PowerShell 用戶跟 Unix命令行大師旗鼓相當,不管你用什么系統(tǒng),都可以使用優(yōu)秀的 Codio(https://codio.com/)
至少你應(yīng)該知道如何切換目錄,如何復(fù)制、移動和刪除文件,以及如何中斷一個命令行程序(通常 Ctrl-C)。如果你想變成終端高手,我建議你學(xué)一學(xué)如何在文件中搜索文本,如何搜索文件和目錄,如何把
命令鏈在一起(老式的“Unix 理念”),以及如何重定向輸出解凍終端是用 Ctrl-Q,所以如果你忽然發(fā)覺終端看起來被凍結(jié)了,試一下 Ctrl-Q,看能不能釋放它
Node 實現(xiàn)簡單的 web 服務(wù)器
如果你之前曾經(jīng)做過靜態(tài)的 HTML 網(wǎng)站,或者有 PHP 或 ASP 背景,可能習(xí)慣用 Web 服務(wù)
器(比如 Apache 或 IIS)提供靜態(tài)文件服務(wù),以便使用瀏覽器通過網(wǎng)絡(luò)查看這些文件。比
如說,如果你創(chuàng)建了一個名為 about.html 的文件,并把它放到了恰當?shù)哪夸浵拢缓缶涂?br>
以訪問 http://localhost/about.html 查看這個文件。根據(jù) Web 服務(wù)器的配置,你甚至可以省
略 .html,但 URL 和文件名之間的關(guān)系很清晰:Web 服務(wù)器知道文件在機器的哪個地方,
并能把它返回給瀏覽器。
Node 所提供的范式跟傳統(tǒng)的 Web 服務(wù)器不同:你寫的程序就是 Web 服務(wù)器。Node 只是
給你提供了一個構(gòu)建 Web 服務(wù)器的框架。
創(chuàng)建
var http = require("http");
http
.createServer(function(req, res) {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello world!");
})
.listen(3000);
console.log("Server started on localhost:3000; press Ctrl-C to terminate....");
事件驅(qū)動編程
Node 的核心理念是事件驅(qū)動編程,很多人接觸事件驅(qū)動編程是從用戶界面開始的:用戶點擊了什么,
然后你處理“點擊事件”。這個類比很好,因為程序員不能控制用戶什么時間點擊或者是
否會點擊,所以事件驅(qū)動編程真的很直觀
路由
路由是指向客戶端提供它所發(fā)出的請求內(nèi)容的機制。對基于 Web 的客戶端 / 服務(wù)器端程序而言,客戶端在 URL 中指明它想要的內(nèi)容,具體來說就是路徑和查詢字符串
靜態(tài)資源服務(wù)
用 Node 提供靜態(tài)資源只適用于初期的小型項目,對于比較大的項目,你應(yīng)該會想用 Nginx 或 CDN 之類的代理服務(wù)器來提供靜態(tài)資源
我們可將它作為跳板去完成更加復(fù)雜的事情。如果我們沿著這條路走下去,寫出越來越復(fù)雜的 Node 程序,最后你可能會得到一個類似于 Express 的東西……幸運的是,我們沒必要這樣做,因為 Express 已經(jīng)存在了,你不用自己花那么多時間去寫基礎(chǔ)設(shè)施類的代碼
腳手架
這個想法很簡單:大多數(shù)項目都需要一定數(shù)量的“套路化”代碼,誰會想每次開始新項目時都重新寫一次這些代碼呢?對此有個簡單的方法,那就是創(chuàng)建一個通用的項目骨架,每次開始新項目時,只需復(fù)制這個骨架,或者說是模板。
案例:HTML5 Boilerplate,它能生成一個很不錯的空白 HTML5 網(wǎng)站
初始化項目
-
npm init --yes生成一個 package.json 文件,注意 main 的入口文件,默認 index.js npm install express --save- 編寫
index.js入口文件內(nèi)容
var express = require("express");
var app = express();
app.set("port", process.env.PORT || 3000);
// 定制 404 頁面
app.use(function(req, res) {
res.type("text/plain");
res.status(404);
res.send("404 - Not Found");
});
// 定制 500 頁面
app.use(function(err, req, res, next) {
console.error(err.stack);
res.type("text/plain");
res.status(500);
res.send("500 - Server Error");
});
app.listen(app.get("port"), function() {
console.log(
"Express started on http://localhost:" +
app.get("port") +
"; press Ctrl-C to terminate."
);
});
app.use 是 Express 添加中間件的一種方法
視圖和布局
Express 支持多種不同的視圖引擎,它們有不同層次的抽象。Express 比較偏好的視圖引擎是 Jade(因為它也是 TJ Holowaychuk 開發(fā)的),Jade 所采用的方式非常精簡:你寫的根本不像是 HTML,因為沒有尖括號和結(jié)束標簽,這樣可以少敲好多次鍵盤。然后,Jade 引擎會將其轉(zhuǎn)換成 HTML Jade 是非常吸引人的,但這種程度的抽象也是有代價的。如果你是一名前端開發(fā)人員,即便你實際上是用 Jade 編寫視圖,也必須理解 HTML,大多數(shù)前端開發(fā)人員都不喜歡他們主要的標記語言被抽象化處理
Handlebars
推薦使用另外一個抽象程度較低的模板框架 Handlebars。Handlebars(基于與語言無關(guān)的流行模板語言 Mustache)不會試圖對 HTML 進行抽象:你編寫的是帶特殊標簽的 HTML,Handlebars 可以借此插入內(nèi)容
- 視圖和靜態(tài)文件
static 中間件可以將一個或多個目錄指派為包含靜態(tài)資源的目錄,其中的資源不經(jīng)過任何特殊處理直接發(fā)送到客戶端。你可以在其中放圖片、CSS 文件、客戶端 JavaScript 文件之類的資源
app.use(express.static(path.join(__dirname, "public")));
- 視圖中的動態(tài)內(nèi)容
視圖真正的強大之處在于它可以包含動態(tài)信息
工欲善其事,必先利其器
git
項目目錄中創(chuàng)建一個文本文件 .gitignore
node_modules
*~
.DS_Store
npm 包
不管什么時候在項目中使用了 Node 模塊,你都要確保它作為依賴項出現(xiàn)在 package.json 文
件中。如果你沒能做到這一點,npm 將無法構(gòu)建出恰當?shù)囊蕾図?,而當其他開發(fā)人員檢出
項目時(或者當你換了一臺機器時),就無法安裝正確的依賴項,包管理器的價值也不能
得到有效發(fā)揮
項目元數(shù)據(jù)
package.json 文件的另一個作用便是存放項目的元數(shù)據(jù),比如項目名稱、作者、授權(quán)信息等。如果你用 npm init 來初始化創(chuàng)建 package.json 文件,它會為你生成必需的域,然后你可以隨時修改它們。如果你想把項目放到 npm 或 Github 上,則對元數(shù)據(jù)的要求會比較嚴格
Node 模塊
Node 模塊和 npm 包是兩個相互關(guān)聯(lián)但又彼此不同的概念。Node 模塊,就像
它的名字一樣,提供了一個模塊化和封裝的機制。npm 包則提供了一種存儲、版本化和引
用項目(不限于模塊)的標準范式
質(zhì)量保證
在 Web 開發(fā)中,質(zhì)量可以分解為四個維度:
- 到達率是指產(chǎn)品的市場普及程度,即查看網(wǎng)站或使用服務(wù)的人數(shù)。到達率和盈利能力是
正相關(guān)關(guān)系:訪問網(wǎng)站的人越多,購買產(chǎn)品或服務(wù)的人就越多。從開發(fā)的角度來看,搜
索引擎優(yōu)化(SEO)對到達率的影響最大,所以我們會在 QA 方案里包含 SEO - 功能,否把用戶留下很大程度上取決于網(wǎng)站功能的質(zhì)量
- 功能關(guān)心的是功能的正確性,而可用性評估的是人機交互(HCI),程序員眼中的“容易”可能跟不懂技術(shù)的用戶眼中的“容易”不一樣
- 審美是四個維度中最主觀的,因此也是跟開發(fā)最不相關(guān)的一個維度,審美具有時間敏感性(審美標準會隨著時間而發(fā)生變化),并且因人而異(受到某一受眾喜愛的東西可能完全激不起其他受眾的興趣)
測試的類型
單元測試和集成測試,一般而言,單元測試在測試邏輯時更實用,也更恰當
QA 技術(shù)概覽
- 頁面測試,用來測試頁面的表示和前端功能。這同時涉及單元測試和集成測
試。我們會用 Mocha 進行頁面測試 - 跨頁測試是對從一個頁面轉(zhuǎn)到另一個頁面的功能的測試,比如電子商務(wù)網(wǎng)站上的結(jié)賬功
能,通常要跨越多個頁面。因為這種測試會涉及多個組件,所以一般被當作集成測試。
這個測試用的是 Zombie.js。 - 邏輯測試會對邏輯域進行單元和集成測試。它只會測試 JavaScript,跟所有表示功能
分開 - 去毛的一般概念是找出可能有錯誤的區(qū)域,SHint
- 鏈接檢查(確保你的網(wǎng)站上沒有破損的鏈接)屬于“唾手可得”的那一類測試
請求和響應(yīng)對象
URL 組成部分
- 協(xié)議:確定如何傳輸請求。我們主要是處理 http 和 https。其他常見的協(xié)議還有 file 和 ftp。
- 主機名標識服務(wù)器,還會有子域名作為主機名的前綴,子域名可以是任何形式的,其中 www 最為常見。子域名通常是可選的。
- 端口: 每一臺服務(wù)器都有一系列端口號,如果省略端口值,那么默認 80 端口負責 HTTP 傳輸,443 端口負責 HTTPS 傳輸。如果不使用 80 和 443 端口,就需要一個大于 1023 1 的端口號。通常使用容易記憶的端口號,如 3000、8080 或 8088
- 路徑: 是應(yīng)用中的頁面或其他資源的唯一標識
- 查詢字符串: 是一種鍵值對集合,是可選的。它以問號(?)開頭,鍵值對則以與號(&)分隔開。所有的名稱和值都必須是 URL 編碼的。對此,JavaScript 提供了一個嵌入式的函數(shù) encodeURIComponent 來處理。例如,空格被加號(+)替換。其他特殊字符被數(shù)字型字符替換。
-
信息片段(或散列)被嚴格限制在瀏覽器中使用,不會傳遞到服務(wù)器。用它控制單頁應(yīng)
用或 AJAX 富應(yīng)用越來越普遍。最初,信息片段只是用來讓瀏覽器展現(xiàn)文檔中通過錨點
標記(<a id="chapter06">)指定的部分
HTTP 請求方法
HTTP 協(xié)議確定了客戶端與服務(wù)器通信的請求方法集合(通常稱為 HTTP verbs)。很顯然,
GET 和 POST 最為常見
請求報頭
我們?yōu)g覽網(wǎng)頁時,發(fā)送到服務(wù)器的并不只是 URL,會發(fā)送“用戶代理”信息(瀏覽器、操作系統(tǒng)和硬件設(shè)備)和其他一些信息。所有能夠確保你了解請求對象頭文件屬性的信息都將會作為請求報頭發(fā)送。如果想查看瀏覽器發(fā)送的信息,可以創(chuàng)建一個非常簡單的 Express 路由來展示一下:
app.get("/headers", function(req, res) {
res.set("Content-Type", "text/plain");
var s = "";
for (var name in req.headers) s += name + ": " + req.headers[name] + "\n";
res.send(s);
});
響應(yīng)報頭
正如瀏覽器以請求報頭的形式發(fā)送隱藏信息到服務(wù)器,當服務(wù)器響應(yīng)時,同樣會回傳一些瀏覽器沒必要渲染和顯示的信息,通常是元數(shù)據(jù)和服務(wù)器信息
它告訴瀏覽器正在被傳輸?shù)膬?nèi)容類型(網(wǎng)頁、圖片、樣式表、客戶端腳本等)。特別要注意的是,不管 URL 路徑是什么,瀏覽器都根據(jù)內(nèi)容類型報頭處理信息
瀏覽器只根據(jù)內(nèi)容類型來決定內(nèi)容該如何渲染。)除了內(nèi)容類型之外,報頭還會指出響應(yīng)信息是否被壓縮,以及使用的是哪種編碼。響應(yīng)報頭還可以包含關(guān)于瀏覽器對資源緩存時長的提示。優(yōu)化網(wǎng)站時需要著重考慮這一點
響應(yīng)報頭還經(jīng)常會包含一些關(guān)于服務(wù)器的信息,一般會指出服務(wù)器的類型,有時甚至?xí)僮飨到y(tǒng)的詳細信息。返回服務(wù)器信息存在一個問題,那就是它會給黑客一個可乘之機,從而使站點陷入危險。非常重視安全的服務(wù)器經(jīng)常忽略此信息,甚至提供虛假信息。禁用 Express 的 X-Powered-By 頭信息很簡單
app.disable("x-powered-by");
請求體
除請求報頭外,請求還有一個主體(就像作為實際內(nèi)容返回的響應(yīng)主體一樣)
- 一般 GET 請求沒有主體內(nèi)
- POST 請求體最常見的媒體類型是 application/x-www-form-urlendcoded,是鍵值對集合的簡單編碼,用 & 分隔(基本上和查詢字符串的格式一樣)
- POST 請求需要支持文件上傳,則媒體類型是 multipart/form-data ,它是一種更為復(fù)雜的格式
- AJAX 請求,它可以使用 application/json
請求對象
請求對象的生命周期始于 Node 的一個核心對象 http.IncomingMessage 的實例。
Express 添加了一些附加功能,除了來自 Node 的req.headers 和req.url ,所有這些方法都由 Express 添加
| 方法 | 說明 |
|---|---|
req.params |
一個數(shù)組,包含命名過的路由參數(shù) |
req.param(name) |
返回命名的路由參數(shù),或者 GET 請求或 POST 請求參數(shù) |
req.query |
一個對象,包含以鍵值對存放的查詢字符串參數(shù)(通常稱為 GET 請求參數(shù)) |
req.body |
一個對象,包含 POST 請求參數(shù),需要中間件能夠解析請求正文內(nèi)容類型 |
req.route |
關(guān)于當前匹配路由的信息。主要用于路由調(diào)試 |
req.cookies/req.singnedCookies |
一個對象,包含從客戶端傳遞過來的 cookies 值 |
req.headers |
從客戶端接收到的請求報頭。 |
req.accepts([types]) |
用來確定客戶端是否接受一個或一組指定的類型(可選類型可以是單個的 MIME 類型,如 application/json 、一個逗號分隔集合或是一個數(shù)組) |
req.ip |
客戶端的 IP 地址。 |
req.path |
請求路徑(不包含協(xié)議、主機、端口或查詢字符串) |
req.host |
一個簡便的方法,用來返回客戶端所報告的主機名。這些信息可以偽造,所以不應(yīng)該用于安全目的 |
req.xhr |
一個簡便屬性,如果請求由 Ajax 發(fā)起將會返回 true |
req.protocol |
用于標識請求的協(xié)議( http 或 https ) |
req.secure |
一個簡便屬性,如果連接是安全的,將返回 true 。等同于 req.protocol==='https'
|
req.url/req.originalUrl |
這些屬性返回了路徑和查詢字符串(它們不包含協(xié)議、主機或端口) |
req.acceptedLanguages |
用來返回客戶端首選的一組(人類的)語言。這些信息是從請求報頭中解析而來的 |
響應(yīng)對象
響應(yīng)對象(通常傳遞到回調(diào)方法,這意味著你可以隨意命名它,通常命名為 res 、 resp 或
response )的生命周期始于 Node 核心對象 http.ServerResponse 的實例.Express 添加了一
些附加功能。我們來看看響應(yīng)對象中最有用的屬性和方法(所有這些方法都是由 Express
添加的)
| 方法 | 說明 |
|---|---|
res.status(code) |
設(shè)置 HTTP 狀態(tài)代碼。Express 默認為 200(成功) |
res.set(name,value) |
設(shè)置響應(yīng)頭。這通常不需要手動設(shè)置 |
res.cookie(name,vaue,[options]),res.clearCookie(name,[options])
|
設(shè)置或清除客戶端 cookies 值。需要中間件支持 |
res.redirect([status],url) |
重定向瀏覽器。默認重定向代碼是 302(建立) |
res.send(body),res.send(status,body) |
向客戶端發(fā)送響應(yīng)及可選的狀態(tài)碼。Express 的默認內(nèi)容類型是 text/html |
res.json(json),res.json(status,json) |
向客戶端發(fā)送 JSON 以及可選的狀態(tài)碼。 |
res.jsonp(json),req.jsonp(status,json) |
向客戶端發(fā)送 JSONP 及可選的狀態(tài)碼。 |
res.type(type) |
一個簡便的方法,用于設(shè)置 Content-Type 頭信息?;旧舷喈斢?res.set('Content-Type','type')
|
res.format(object) |
允許你根據(jù)接收請求報頭發(fā)送不同的內(nèi)容 |
res.sendFile(path,[option],[callback]) |
根據(jù)路徑讀取指定文件并將內(nèi)容發(fā)送到客戶端 |
更多信息
如果你需要的信息沒在文檔中,有時就不得不深入研究 Express 源碼
源碼的路徑說明和說明
lib/application.js是 Express 主接口。如果想了解中間件是如何接入的,或視圖是如何被渲染的,可以看這里。lib/express.js這是一個相對較短的 shell,是 lib/application.js 中 Connect 的功能性擴展,它返回一個函數(shù),可以用 http.createServer 運行 Express 應(yīng)用lib/request.js擴展了 Node 的 http.IncomingMessage 對象,提供了一個穩(wěn)健的請求對象。關(guān)于請求對象屬性和方法的所有信息都在這個文件里。lib/response.js擴展了 Node 的 http.ServerReponse 對象,提供響應(yīng)對象。關(guān)于響應(yīng)對象的所有屬性和方法都在這個文件里lib/router/route.js提供基礎(chǔ)路由支持。盡管路由是應(yīng)用的核心,但這個文件只有不到 200 行,你會發(fā)現(xiàn)它非常地簡單優(yōu)雅
內(nèi)容渲染(掌握)
渲染內(nèi)容用 res.render ,它最大程度地根據(jù)布局渲染視圖。如果想寫一個快速測試頁,也許會用到 res.send,你可以使用 req.query 得到查詢字符串的值,使用 req.session 得到會話值,或使用 req.cookie/req.singedCookies 得到 cookies 值
- 基本用法
app.get("/about", function(req, res) {
res.render("about");
});
- 200 以外的響應(yīng)代碼
app.get("/error", function(req, res) {
res.status(500);
res.render("error");
});
//或者是一行代碼
app.get("/error", function(req, res) {
res.status(500).render("error");
});
- 將上下文傳遞給視圖,包括查詢字符串、cookie 和 session 值
app.get("/greeting", function(req, res) {
res.render("about", {
message: "welcome",
style: req.query.style,
userid: req.cookie.userid,
username: req.session.username
});
});
- 沒有布局的視圖渲染
// 下面的 layout 沒有布局文件,即 views/no-layout.handlebars
// 必須包含必要的 HTML
app.get("/no-layout", function(req, res) {
res.render("no-layout", { layout: null });
});
- 使用定制布局渲染視圖
// 使用布局文件 views/layouts/custom.handlebars
app.get("/custom-layout", function(req, res) {
res.render("custom-layout", { layout: "custom" });
});
- 渲染純文本輸出
app.get("/test", function(req, res) {
res.type("text/plain");
res.send("this is a test");
});
- 添加錯誤處理程序
// 這應(yīng)該出現(xiàn)在所有路由方法的結(jié)尾
// 需要注意的是,即使你不需要一個 " 下一步 " 方法
// 它也必須包含,以便 Express 將它識別為一個錯誤處理程序
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).render("error");
});
- 添加一個 404 處理程序
// 這應(yīng)該出現(xiàn)在所有路由方法的結(jié)尾
app.use(function(req, res) {
res.status(404).render("not-found");
});
表單處理(掌握)
當你處理表單時,表單信息一般在 req.body 中(或者偶爾在 req.query 中)。你可以使用 req.xhr 來判斷是 AJAX 請求還是瀏覽請求
- 基本表單處理
// 必須引入中間件 body-parser
app.post("/process-contact", function(req, res) {
console.log(
"Received contact from " + req.body.name + " <" + req.body.email + ">"
);
// 保存到數(shù)據(jù)庫……
res.redirect(303, "/thank-you");
});
- 更強大的表單處理
// 必須引入中間件 body-parser
app.post("/process-contact", function(req, res) {
console.log(
"Received contact from " + req.body.name + " <" + req.body.email + ">"
);
try {
// 保存到數(shù)據(jù)庫……
return res.xhr
? res.render({ success: true })
: res.redirect(303, "/thank-you");
} catch (ex) {
return res.xhr
? res.json({ error: "Database error." })
: res.redirect(303, "/database-error");
}
});
Handlebars 模板引擎
模板解決了在目標語言中編寫代碼的問題,同時也讓插入動態(tài)數(shù)據(jù)成為了可能
Node 的世界里,有許多模板引擎可供選擇,那么如何挑選呢?
- 性能
- 客戶端、服務(wù)端或兼而有之?-選擇那些在兩端都表現(xiàn)優(yōu)秀的模板引擎
- 抽象-你私下里厭惡 HTML 已久,希望有什么東西能把你從那些尖括號中拯救出來但是,作為一個 Web 開發(fā)者,HTML 是核心
Handlebars 是另一個流行的模板引擎 Mustache 的擴展
理解模板引擎的關(guān)鍵在于 context(上下文環(huán)境)。當你渲染一個模板時,便會傳遞給模板引擎一個對象,叫作上下文對象,它能讓替換標識運行
注釋
Handlebars 的注釋看起來像 {{! comment goes here }}
服務(wù)器端模板
服務(wù)器端模板除了隱藏實現(xiàn)細節(jié),還支持模板緩存,這對性能很重要。模板引擎會緩存已編譯的模板(只有在模板發(fā)生改變的時候才會重新編譯和重新緩存),這會改進模板視圖的性能,默認情況下,視圖緩存會在開發(fā)模式下禁用,在生產(chǎn)模式下啟用。如果想顯式地啟用視圖緩存,可以這樣做:
app.set('view cache', true)
Express 中使用布局
//我們創(chuàng)建視圖引擎時,會指定一個默認的布局
var handlebars = require('express3-handlebars').create({ defaultLayout: 'main' });
//Express 會在 views 子目錄中查找視圖,在 views/layouts 下查找布局。所以如
//果有一個叫作 views/foo.handlebars 的視圖,可以這樣渲染它
app.get('/foo', function(req, res){
res.render('foo');
});
你擁有的模板越多,需要維護的基礎(chǔ) HTML 布局就越多
客戶端 Handlebars
我們既可以將 Handlebars 放在靜態(tài)資源中引入,也可以使用一個 CDN
閱讀記錄中...持續(xù)更新