摘要:一個(gè)標(biāo)準(zhǔn)性的事件就是年的橫空出世。引擎快速處理能力和異步編程風(fēng)格,讓開(kāi)發(fā)者從多線程中解脫了出來(lái)。其次,通過(guò)異步編程范式將其高并發(fā)的能力發(fā)揮的淋漓盡致。它也僅僅是一個(gè)處理請(qǐng)求并作出響應(yīng)的函數(shù),并無(wú)任何特殊之處。
在正式學(xué)習(xí) Express 內(nèi)容之前,我們有必要從大的方面了解一下 Node.js 。
在很長(zhǎng)的一段時(shí)間里,JavaScript 一門(mén)編寫(xiě)瀏覽器中運(yùn)行腳本的語(yǔ)言。不過(guò)近些年,隨著互聯(lián)網(wǎng)的發(fā)展以及技術(shù)進(jìn)步,JavaScript 迎來(lái)了一個(gè)集中爆發(fā)的時(shí)代。一個(gè)標(biāo)準(zhǔn)性的事件就是 09 年 Node.js 的橫空出世。
Node.js 由 Google Chrome 的 V8 引擎發(fā)展而來(lái),它能夠讓 JavaScript 運(yùn)行在服務(wù)端。從而極大的拓展了 JavaScript 的應(yīng)用場(chǎng)景也讓 JavaScript 全棧成為了一個(gè)熱門(mén)話題。開(kāi)發(fā)者不必再去學(xué)習(xí) Ruby、Python、Java 等語(yǔ)言和框架,僅僅依靠 JavaScript 就能完成前后端的大部分開(kāi)發(fā)任務(wù)。
雖然,從某些方面來(lái)說(shuō) JavaScript 并不完美甚至還有一些設(shè)計(jì)缺陷,但是這并不影響 Nodejs 的流行。V8 引擎快速處理能力和異步編程風(fēng)格,讓開(kāi)發(fā)者從多線程中解脫了出來(lái)。其中,前后端同一技術(shù)??梢哉f(shuō)是它最大的殺手锏。而日益豐富的生態(tài)環(huán)境也讓 JavaScript 受到開(kāi)發(fā)者越來(lái)越多的關(guān)注,使用 Node.js 進(jìn)行開(kāi)發(fā)也變成了一件非常符合潮流的事情了。
和瀏覽器環(huán)境中的 JavaScript 一樣,Node.js 也只提供了構(gòu)建應(yīng)用基本所需的底層接口和特性。而這些底層接口一般都很冗長(zhǎng)、難用。所以有人就在 Node.js 的基礎(chǔ)上實(shí)現(xiàn)了 Express 框架。其基本理念與 jQuery 類似,通過(guò)對(duì)底層接口進(jìn)行了封裝,在簡(jiǎn)化代碼的同時(shí)提供更高級(jí)的接口。另外,Express 拓展性也非常強(qiáng)??蚣鼙旧砼c程序的架構(gòu)和業(yè)務(wù)無(wú)關(guān),并且你還可以通過(guò)第三方庫(kù)進(jìn)行功能拓展。
Node.js 應(yīng)用場(chǎng)景Node.js (通常簡(jiǎn)稱為 Node )是一個(gè) JavaScript 代碼的運(yùn)行平臺(tái)。雖然大多數(shù)情形下 JavaScript 都運(yùn)行在瀏覽器中,但是并沒(méi)有任何地方規(guī)定其只能運(yùn)行在瀏覽器中。作為一門(mén)編程語(yǔ)言,本質(zhì)上它與 Ruby、Python、C++、PHP 并沒(méi)有什么區(qū)別。就像你可以使用 python myfile.py 來(lái)運(yùn)行 Python 腳本,你可以使用 ?node myfile.js 來(lái)執(zhí)行 JavaScript 程序。
但是 Node 到底有啥優(yōu)點(diǎn)值得我們?cè)诜?wù)端開(kāi)發(fā)是嘗試呢?
首先,Node.js 的 JavaScript 引擎非???。畢竟,它是基于以速度著稱的 Google Chrome V8 引擎,可以每秒執(zhí)行幾千條 JavaScript 指令。
其次,Node.js 通過(guò)異步編程范式將其高并發(fā)的能力發(fā)揮的淋漓盡致。
用現(xiàn)實(shí)生活中的烘焙做類比最恰當(dāng)不過(guò)了。假設(shè)現(xiàn)在我需要制作一些松餅,那么首先就需要把面粉弄好。而此時(shí)我是無(wú)法抽身做其他的事情的。但是,一旦我把松餅送進(jìn)烤箱,我就可以抽身做其他的事情而不必干等。
在 Node.js 中,客戶端可能隨時(shí)都會(huì)給服務(wù)端發(fā)送請(qǐng)求。有可能在你處理一個(gè)請(qǐng)求時(shí),另一個(gè)請(qǐng)求也被客戶端送達(dá)了。假設(shè),兩個(gè)請(qǐng)求都需要訪問(wèn)數(shù)據(jù)庫(kù)。那么就可以在第一個(gè)請(qǐng)求進(jìn)行數(shù)據(jù)庫(kù)操作時(shí),轉(zhuǎn)去處理第二個(gè)請(qǐng)求。雖然不能同時(shí)對(duì)兩者做成響應(yīng),但是我們可以使用異步方式跳過(guò)對(duì)耗時(shí)操作結(jié)果的等待直接處理后續(xù)請(qǐng)求。而其他的一些運(yùn)行環(huán)境默認(rèn)是沒(méi)有此能力的。例如,Ruby on Rails 同時(shí)時(shí)間只能處理一個(gè)請(qǐng)求。如果想提高程序的并發(fā)能力,那么你就需要去購(gòu)買(mǎi)更多的服務(wù)器。
下圖可以清晰的看出兩者的區(qū)別:
與同步方式相比,異步處理的效率明顯要更高,雖然異步代碼也不是并行處理。
當(dāng)然,這并不是說(shuō)異步處理機(jī)制讓 Node.js 是世界上最快的語(yǔ)言之一。Node.js 雖然能夠最大化壓制單核 CPU 的性能,但是還是無(wú)法與多核處理能力相媲美。其他語(yǔ)言中可以讓你利用多核能力同時(shí)執(zhí)行多個(gè)任務(wù)。像之前和烘培一樣:你可以購(gòu)買(mǎi)更多的烤箱來(lái)同時(shí)烤更多的餅干。Node 正在開(kāi)始支持這個(gè)能力,但是它并不像其他語(yǔ)言中那樣重要。
就我個(gè)人而言,因?yàn)樾阅芏x擇 Node.js 并不是最重要的依據(jù),雖然,它確實(shí)比 Ruby、Python 等腳步語(yǔ)言要快。最大的理由是,它在前后端開(kāi)發(fā)中使用同一種語(yǔ)言。
通常,在編寫(xiě) Web 應(yīng)用程序時(shí)你都會(huì)要使用 JavaScript。但是在 Node.js 出現(xiàn)之前,前后端的開(kāi)發(fā)必須使用不同的語(yǔ)言進(jìn)行。為此你需要學(xué)習(xí)多種的語(yǔ)言和框架。有了 Node.js 之后,你就可以使用一門(mén)語(yǔ)言在前后端開(kāi)發(fā)中自由切換,這是最吸引人的地方。
什么是 Express ?Express 是一個(gè)基于 Node.js 封裝的上層服務(wù)框架,它提供了更簡(jiǎn)潔的 API 更實(shí)用的新功能。它通過(guò)中間件和路由讓程序的組織管理變的更加容易;它提供了豐富的 HTTP 工具;它讓動(dòng)態(tài)視圖的渲染變的更加容易;它還定義了一組可拓展標(biāo)準(zhǔn)。
Node.js 的功能通過(guò)一個(gè)簡(jiǎn)單的 JavaScript 函數(shù),你就可以利用 Node.js 創(chuàng)建一個(gè) Web 程序。該函數(shù)用于監(jiān)聽(tīng)來(lái)自瀏覽器或者其他設(shè)備的發(fā)起的網(wǎng)絡(luò)請(qǐng)求。當(dāng)接收到一個(gè)請(qǐng)求后,函數(shù)會(huì)分析請(qǐng)求的內(nèi)容并做成相應(yīng)的處理。例如,當(dāng)你請(qǐng)求站點(diǎn)主頁(yè)時(shí),該函數(shù)就會(huì)知道知道你的目的并將主頁(yè)的 HTML 渲染出來(lái)。如果是請(qǐng)求某個(gè) API 接口,該函數(shù)就會(huì)把對(duì)應(yīng)的 JSON 數(shù)據(jù)返回給客戶端。
假設(shè),現(xiàn)在需要服務(wù)器返回當(dāng)前時(shí)間和時(shí)區(qū)信息給用戶,那么該程序大致包括如下功能:
如果客戶端發(fā)起主頁(yè)請(qǐng)求,Web 應(yīng)用將會(huì)返回一個(gè)包含所需信息的 HTML 。
如果客戶端訪問(wèn)地址錯(cuò)誤,Web 應(yīng)用將會(huì)返回 HTTP 404 錯(cuò)誤,并附帶一段錯(cuò)誤描述。
如果直接在 Node.js 之上構(gòu)建該應(yīng)用而不使用 Express 的話,那么完整流程圖大抵如下:
在上述流程中,開(kāi)發(fā)人員只需要關(guān)注圓圈部分內(nèi)容處理。
這個(gè)用于處理瀏覽器請(qǐng)求的 JavaScript 函數(shù)叫做請(qǐng)求處理函數(shù)(request handler)。它也僅僅是一個(gè)處理請(qǐng)求并作出響應(yīng)的 JavaScript 函數(shù),并無(wú)任何特殊之處。Node.js 的 HTTP 服務(wù)會(huì)接管其中的網(wǎng)絡(luò)連接,所以你無(wú)需關(guān)注和處理復(fù)雜的網(wǎng)絡(luò)協(xié)議內(nèi)容。
從代碼角度來(lái)說(shuō),該函數(shù)包含兩個(gè)參數(shù):一個(gè)是網(wǎng)絡(luò)請(qǐng)求 request 對(duì)象 ,另一個(gè)表示網(wǎng)絡(luò)響應(yīng)的 response 對(duì)象。在前面時(shí)間信息應(yīng)用中,該請(qǐng)求處理函數(shù)會(huì)檢查請(qǐng)求 URL 。如果請(qǐng)求的是主頁(yè),那么就返回成功的響應(yīng)頁(yè)面。否則,返回 404 錯(cuò)誤。沒(méi)有 Node.js 應(yīng)用中都是這么處理的:編寫(xiě)處理函數(shù)對(duì)請(qǐng)求作出響應(yīng),非常的簡(jiǎn)單。
問(wèn)題在于,Node.js 的 API 對(duì)開(kāi)發(fā)者來(lái)說(shuō)并不是非常友好。例如,如果我們想發(fā)送一個(gè) JPEG 圖片的話,可能需要至少 45 行代碼才行。創(chuàng)建可復(fù)用 HTML 模版則更復(fù)雜。另外,Node.js 的 HTTP 模塊雖然強(qiáng)大,但是仍然缺少一些實(shí)用特性。
Express 的出現(xiàn)就是為了解決這些問(wèn)題,讓你能夠高效的使用 Node.js 來(lái)編寫(xiě) Web 應(yīng)用。
Express 給 Node.js 帶來(lái)了什么?從大的方面來(lái)說(shuō),Express 為 Node.js 的 HTTP 模塊帶來(lái)了兩大特性:
通過(guò)提供大量易用接口,簡(jiǎn)化了程序的復(fù)雜度。例如上面放松 JPEG 圖片問(wèn)題,Express 可以將代碼壓縮帶一行。
它允許對(duì)請(qǐng)求處理函數(shù)進(jìn)行拆分,將其重構(gòu)為很多負(fù)責(zé)特定請(qǐng)求的小型請(qǐng)求處理函數(shù)。這便于模塊化和后期維護(hù)。
與上圖相比,下圖是 Express 處理請(qǐng)求的大致流程:
與之前一樣,開(kāi)發(fā)者只需要關(guān)注圓圈部分的內(nèi)容。
雖然,圖看起來(lái)比前面復(fù)雜,但是實(shí)際開(kāi)發(fā)卻更簡(jiǎn)單,本質(zhì)上它主要做了兩件事:
與之前一個(gè)大型的 request 請(qǐng)求處理函數(shù)不同,這里使用大量小型處理函數(shù)。有些函數(shù)每次都會(huì)執(zhí)行(例如,請(qǐng)求日志),而有些函數(shù)只在特定情形下才會(huì)觸發(fā)(例如,404 錯(cuò)誤)。Express 有很多使用的工具能夠?qū)@些處理函數(shù)進(jìn)行區(qū)分。
請(qǐng)求處理函數(shù)中有兩個(gè)參數(shù):request 和 response。Node 的 HTTP 可以對(duì)其做些基本處理,例如:獲取瀏覽器的 user-agent 。Express 則更為強(qiáng)大,你可以獲取到訪問(wèn)者 IP 地址,以及解析優(yōu)化過(guò)的 URL 請(qǐng)求對(duì)象。esponse 對(duì)象也同樣得到了增強(qiáng)。通過(guò)類似 sendFile 這樣的函數(shù)將文件傳輸代碼壓縮至一行。這極大的簡(jiǎn)化了處理函數(shù)的功能實(shí)現(xiàn)。
利用 Express 提供的簡(jiǎn)潔 API 接口,通過(guò)編寫(xiě)小型 request 請(qǐng)求處理函數(shù),可以極大的壓縮代碼量提高開(kāi)發(fā)效率。
Express 的最小化理念雖然 Express 是一個(gè)框架,但是它的編程規(guī)范非常靈活。你可以用它編寫(xiě)各種類型的應(yīng)用,從視頻聊天到個(gè)人博客等等。另外,Express 本身并不是百寶箱,你可能會(huì)在實(shí)際開(kāi)發(fā)中需要使用大量第三方類庫(kù)。這些類庫(kù)能幫你解決一些次要問(wèn)題,這樣你可以將關(guān)注點(diǎn)地放在那些重要的問(wèn)題上,然后發(fā)揚(yáng) Unix do-one-thing-well 的哲學(xué)將事情處理好。
但是這種最小化理念也是一把雙刃劍。一方面,Express 非常靈活可靠,而且不會(huì)引入那些無(wú)用的垃圾代碼。另一方面,與其他框架相比這種簡(jiǎn)潔不可避免導(dǎo)致了部分功能缺失。這意味需要在程序架構(gòu)上做更多的功課,并且在出現(xiàn)問(wèn)題后要花時(shí)間去尋找第三方模塊。離開(kāi)箱即用還差一點(diǎn)。
有人喜歡靈活多變的框架,而有人則喜歡那些結(jié)構(gòu)固定的框架。例如,PayPal 雖然也使用 Express,但是卻制定了嚴(yán)格的規(guī)范來(lái)約束其開(kāi)發(fā)者。Express 本身并不關(guān)注程序架構(gòu),所以程序員可以根據(jù)偏好自行選擇。由于對(duì)程序有著絕對(duì)控制權(quán),所以一旦你做出不明智的決策,那么后面的坑你就慢慢爬吧。
對(duì)于大型框架和極簡(jiǎn)框架的優(yōu)劣,從來(lái)都沒(méi)有固定的正確答案,所以我們無(wú)須太過(guò)糾結(jié)。這里,我只希望你記住 Express 是一個(gè)極簡(jiǎn)框架。
Express 的核心Express 非常簡(jiǎn)潔而且對(duì) Node.js 的封裝效果也非常棒,而這一切都源于框架中的四個(gè)設(shè)計(jì)。
中間件正如之前提到的,原生的 Node.js 使用一個(gè) request 處理函數(shù)應(yīng)對(duì)所有請(qǐng)求并做出響應(yīng)。
Middleware 這個(gè)名字起的并不好,但是這個(gè)術(shù)語(yǔ)并不是 Express 獨(dú)有,相反它已經(jīng)存在很久了。概念非常簡(jiǎn)單:我們不采用一個(gè)巨大的 request 請(qǐng)求處理函數(shù),相反我們將一系列簡(jiǎn)單的處理函數(shù)組合起來(lái)。每一個(gè)小的處理函數(shù)對(duì)應(yīng)一個(gè)小任務(wù),而這些處理函數(shù)就被稱為中間件。
中間件可以處理各種任務(wù),從記錄請(qǐng)求到發(fā)送靜態(tài)文件到設(shè)置 HTTP 頭部。例如,應(yīng)用中使用的第一個(gè)中間件功能可能就是記錄服務(wù)器中每個(gè)請(qǐng)求的 logger-log。當(dāng)日志記錄完成后,它將繼續(xù)執(zhí)行調(diào)用鏈中的下一個(gè)中間件。而下一個(gè)中間件功能可能會(huì)去驗(yàn)證用戶。如果權(quán)限不夠,就會(huì)使用“未授權(quán)”進(jìn)行提示。反之則繼續(xù)執(zhí)行下一個(gè)中間件。此時(shí)中間件功能可能會(huì)是渲染主頁(yè)并結(jié)束響應(yīng)。下圖演示了這兩種情形:
在圖中可以看出,記錄日志的中間件位于第一個(gè)并且肯定會(huì)被執(zhí)行。緊接著就是執(zhí)行權(quán)限認(rèn)證的中間件。如果用戶權(quán)限滿足的話就繼續(xù)執(zhí)行下一個(gè)中間件,否則就不再執(zhí)行后續(xù)中間件。
中間件最大的特點(diǎn)就是其相對(duì)來(lái)說(shuō)比較標(biāo)準(zhǔn),這也意味著開(kāi)發(fā)者可以通過(guò)為 Express 開(kāi)發(fā)中間件來(lái)拓展其功能。同時(shí),這也許意味著某些通用的中間件,很有可能已經(jīng)有人開(kāi)發(fā)過(guò)來(lái),例如: LESS 和 SCSS 等靜態(tài)文件的編譯、權(quán)限控制、cookies 和 sessions 的解析。
路由相比中間件,Routing 顯然更好。與中間價(jià)類似,路由對(duì)請(qǐng)求處理函數(shù)進(jìn)行了拆分。不同的是,路由根據(jù)請(qǐng)求的 URL 和 HTTP 方法來(lái)決定處理方式的。
例如,你的程序中有一個(gè)主頁(yè)和一個(gè)留言板頁(yè)面。當(dāng)用戶使用 GET 去請(qǐng)求主頁(yè)時(shí),Express 會(huì)返回對(duì)應(yīng)的主頁(yè)內(nèi)容。對(duì)留言板的請(qǐng)求的處理也是如此。如果用戶通過(guò) POST 方法在留言板頁(yè)面中進(jìn)行了留言操作的話,路由需要做出對(duì)應(yīng)處理并刷新頁(yè)面。
類似于中間件,上述路由的處理也是通過(guò)處理函數(shù)進(jìn)行定義的。而不同的行為會(huì)調(diào)用不同的處理函數(shù)。
Express 中的中間件和路由相輔相成。例如:你可以一邊記錄請(qǐng)求日志,同時(shí)對(duì)主頁(yè)路由做出響應(yīng)。
子應(yīng)用Express 應(yīng)用通常都很小,甚至可以是一個(gè)文件。隨著應(yīng)用規(guī)模的擴(kuò)張,可能你會(huì)將其進(jìn)行拆分為多個(gè)文件和文件夾。雖然 Express 對(duì)應(yīng)用的規(guī)模增長(zhǎng)沒(méi)有明確的指導(dǎo)規(guī)則。但是我們可以通過(guò) sub-applications 這一重要特性來(lái)作出應(yīng)對(duì)。 在 Express 術(shù)語(yǔ)中這些只應(yīng)用也被稱為路由器。
通過(guò)實(shí)現(xiàn)正常規(guī)模的路由器子應(yīng)用,可以將一個(gè)大型應(yīng)用進(jìn)行模塊拆分。甚至你可以對(duì)某些子應(yīng)用進(jìn)行更細(xì)致的拆分。例如,在應(yīng)用中可能存在管理后臺(tái)、單頁(yè)應(yīng)用、API 接口 等等幾個(gè)子模塊。這時(shí),你就可以將這些子模塊作為一個(gè)子應(yīng)用來(lái)實(shí)現(xiàn)。詳情如下:
當(dāng)程序規(guī)模變大之后,該特性的優(yōu)勢(shì)將會(huì)逐步凸顯出來(lái)。
易用的 API 函數(shù)Express 由中間件和路由構(gòu)成,在其中你需要編寫(xiě)大量的異步處理函數(shù)來(lái)實(shí)現(xiàn)相關(guān)功能。
為了使處理過(guò)程更加高效正確,Express 在原生的 Node.js 基礎(chǔ)上進(jìn)行了大量的封裝。在壓縮代碼量提高效率的同時(shí)也降低了人為錯(cuò)誤的概率。除了發(fā)送文件之外,Express 提供的 HTML 渲染功能也讓原生 Node.js 望塵莫及。另外在請(qǐng)求解析方面,Express 也做了非常多的工作。
跟前面的特性不一樣的是,在保持功能強(qiáng)大的同時(shí)這些易用的函數(shù)并不會(huì)對(duì)應(yīng)用造成負(fù)面影響。
Express 生態(tài)環(huán)境像其他的工具一樣,Express 并不是遺世獨(dú)立的。
它存活于 Node.js 的生態(tài)中,所有你能找到大量的第三發(fā)模塊提升你的開(kāi)發(fā)效率,例如數(shù)據(jù)庫(kù)連接驅(qū)動(dòng)。因?yàn)镋xpress 可拓展性極強(qiáng),所有整個(gè)生態(tài)中存在大量為 Express 開(kāi)發(fā)的類庫(kù)。
Express 跟其他框架的比較Express 既不是第一個(gè) Web 框架,當(dāng)然更不會(huì)是最后一個(gè)。
同樣,Express 也不是 Node.js 生態(tài)中的唯一框架??赡芩畲蟮母?jìng)爭(zhēng)對(duì)手就是 Hapi.js 了。與 Express 類似,它也有路由、中間件這就概念。不過(guò)不同的是它沒(méi)有基于 Node.js 的 HTTP 模塊來(lái)處理網(wǎng)絡(luò)請(qǐng)求,而是有 Walmart 開(kāi)發(fā)的網(wǎng)絡(luò)模塊。該模塊被 Mozilla,OpenTable 和 NPM 所接受并在真實(shí)程序中檢驗(yàn)過(guò)。作為 Express 的最大競(jìng)爭(zhēng)對(duì)手,因此我懷疑雙方的開(kāi)發(fā)人員可能彼此抱有不小敵意。
在 Node.js 世界中最流行的大型框架非全棧式的 Meteor 莫屬。相比自由靈活的 Express ,Metero 有著非常嚴(yán)格的程序結(jié)構(gòu)。不同于 Express 只關(guān)注 HTTP 層的處理,Meteor 作為全??蚣芸梢酝瑫r(shí)運(yùn)行在客戶端和服務(wù)端。當(dāng)然,這僅僅只是設(shè)計(jì)上的選擇說(shuō)不上到底誰(shuí)更優(yōu)秀。
跟 Express 基于 Node.js 進(jìn)行封裝類似,也有人對(duì) Express 進(jìn)行更高級(jí)的封裝。例如,PayPal 創(chuàng)造的 Kraken 。盡管從技術(shù)角度來(lái)說(shuō),Kraken 不過(guò)只是 Express 的一個(gè)中間件而已。但是,它還是做了不少的事情,例如:中間件的安全綁定。Sails.js 則是另一個(gè)以 Express 為基礎(chǔ)的新型框架,它內(nèi)置了數(shù)據(jù)庫(kù)、WebSocket 集成、API 生產(chǎn)等等功能。所有的這些框架,都是 Express 的一種相對(duì)固定化的封裝實(shí)現(xiàn)。
Express 最主要的幾個(gè)特性之一就是中間件。Connect 是一個(gè)僅作用于 Node.js 和中間件的框架。它沒(méi)有提供路由和易用函數(shù)接口。而 Express 曾經(jīng)在它的中間件層中使用了 Connect。雖然現(xiàn)在被拋棄了,但是 Express 中間件一直都完全兼容 Connect 中間件。這意味著 Express 的火力得到了更大的提升。
除了上面提到的這些,還有很多使用其它語(yǔ)言實(shí)現(xiàn)的 Web 框架。
Express 的很多靈感都來(lái)自于 Ruby 世界中的輕型 Web 框架 Sinatra。與 Express 類似,Sinatra 中也有路由和中間件功能。Sinatra 框架思想被其他很多語(yǔ)言所借鑒并且重新實(shí)現(xiàn),如果你曾經(jīng)用過(guò)這類框架的話,那么對(duì) Express 一定不會(huì)陌生。當(dāng)然,Express 也借鑒了 Python 中的 Bottle 和 Flask 框架。
相應(yīng)的,Express 與 Django、Ruby on Rails、ASP.NET 等框架差距巨大。這些框架都十分龐大,而且程序結(jié)構(gòu)也相對(duì)固定功能更為豐富。而且,Express 與 PHP 也差異明顯,雖然都是運(yùn)行在服務(wù)上但是后者與 HTML 緊耦合。
Express 僅僅是服務(wù)端 Web 框架中的一種,所以我們不能在這里說(shuō) Express 就一定比其他的框架好。它具備一些獨(dú)有的特性,例如,Node.js 的性能以及前后端統(tǒng)一的語(yǔ)言。但是與之同時(shí),它的功能遠(yuǎn)比其他框架來(lái)的少而去 JavaScript 也并不是一門(mén)得到廣大開(kāi)發(fā)者認(rèn)可的“好”語(yǔ)言。脫離具體場(chǎng)景討論優(yōu)劣勢(shì)沒(méi)有意義的,下面我們就看看 Express 一些適用場(chǎng)景。
Express 的應(yīng)用場(chǎng)景理論上來(lái)說(shuō),Express 可以用來(lái)構(gòu)建任何 Web 應(yīng)用。對(duì)所有請(qǐng)求作出響應(yīng)這件事上述提到的框架同樣能夠做到。所以,為什么要選擇 Express 呢?
最大的優(yōu)點(diǎn)就是 Node.js 中編寫(xiě)的 JavaScript 可以在瀏覽器和客戶端實(shí)現(xiàn)共享。從代碼復(fù)用角度來(lái)說(shuō),這種情況是最理想的。從心理角度來(lái)說(shuō)也非常有用,開(kāi)發(fā)過(guò)程中無(wú)需進(jìn)行服務(wù)器模式和客戶端模式的切換。前端開(kāi)發(fā)者可以在不學(xué)習(xí)新語(yǔ)言的情況下直接就可以編寫(xiě)后端代碼。當(dāng)然,前端開(kāi)發(fā)者還是需要學(xué)習(xí)一些新內(nèi)容的,不然這本書(shū)就沒(méi)存在的必要了。
Express 可以幫助你做到這一點(diǎn),人們已經(jīng)為這個(gè)技術(shù)棧擬好了名稱:MEAN 。像 “LAMP” 代表 Linux、Apache、MySQL 和 PHP 一樣,“MEAN” 表示 MongoDB、Express、Angular 和 Node.js。人們之所以對(duì)它喜愛(ài)有加是因?yàn)樗羌?JavaScript 技術(shù)棧。
Express 常用于驅(qū)動(dòng)單頁(yè)應(yīng)用程序(SPA)。SPA 在前端重度依賴 JavaScript,而且通常需要一個(gè)服務(wù)器組件。大多數(shù)服務(wù)器只需要簡(jiǎn)單的提供 HTML、CSS 和 JavaScript ,但是有時(shí)候 REST API 也是常規(guī)需求。Express 可以同時(shí)完成這兩件任務(wù),既可以提供 HTML 也非常適合構(gòu)建 API 。 Express 相對(duì)較低的學(xué)習(xí)曲線使得前端開(kāi)發(fā)者在幾乎無(wú)需學(xué)習(xí)新內(nèi)容的情況下搭建一個(gè) SPA 服務(wù)。
當(dāng)你使用 Express 編寫(xiě)應(yīng)用的時(shí)候就決定了你必須使用 MEAN 技術(shù)棧中的 E 和 N 部分,而對(duì)于另外兩個(gè) Express 沒(méi)有做出過(guò)限定你完全可以采用不同的方案。例如,可以使用 Backbone.js 替換其中的 Angular,構(gòu)成 MEBN 技術(shù)棧。使用 SQL 替換 MongoDB 構(gòu)成 SEAN 技術(shù)棧。雖然 MEAN 術(shù)語(yǔ)很常見(jiàn)而且配置也非常流行,但是你完全可以更具需要自行選擇。在這本書(shū)中我們將涵蓋的技術(shù)棧是 MEN:MongoDB、Express 和 Node.js。
另外 Express 還具有一些實(shí)時(shí)特性。雖然其他語(yǔ)言也支持 WebSocket 和 WebRTC,但是 Node.js 似乎要更強(qiáng)。這意味著你可以將這些特性應(yīng)用到 Express 程序中。因?yàn)?Node.js 能做的,Express 一樣不少。
Node.js 和 Express 的第三方模塊社區(qū)中存在大量可以在 Express 中使用的模塊。有一些是 Express 獨(dú)占的,這些模塊與路由和中間件的特性高度兼容。其他的非獨(dú)占模塊也能提升 Express 應(yīng)用的開(kāi)發(fā)體驗(yàn)和程序性能。
如果你曾經(jīng)有過(guò) ERB、Jinja2、HAML 等模版引擎的使用經(jīng)驗(yàn)的話,你就會(huì)發(fā)現(xiàn) Express 自帶的功能在渲染 HTML 方面簡(jiǎn)直就是弱雞。好在 Express 還可以使用 EJS 和 Jade 這些社區(qū)模版引擎來(lái)解決這個(gè)問(wèn)題。
另外,Express 本身并沒(méi)有對(duì)數(shù)據(jù)庫(kù)做支持。你可以通過(guò)文件、關(guān)系數(shù)據(jù)庫(kù)、或者其他機(jī)制來(lái)實(shí)現(xiàn)數(shù)據(jù)保存。不過(guò)后面將會(huì)介紹在 Express 中如何通過(guò) Mongoose 來(lái)調(diào)用 MongoDB 數(shù)據(jù)庫(kù)。
需要注意的一點(diǎn)是:并不存在 Express 模塊這一概念,所以第三方庫(kù)都是 Node.js 模塊。Node.js 模塊與 Express 相互兼容并且能夠配合其工作。所有這些某塊都是在 npm 倉(cāng)庫(kù)注冊(cè)的 JavaScript 代碼塊,并且可以使用一致的方法進(jìn)行安裝。與其他環(huán)境中一樣,模塊之間可以相互依賴,并且不同模塊可以相互配合。另外,Express 也不過(guò)是 Node.js 中的一個(gè)模塊而已。
Hello World每次學(xué)習(xí)新內(nèi)容的時(shí)候,絕大多數(shù)都是從 Hello World 開(kāi)始。
那么現(xiàn)在我們來(lái)看看如何使用 Express 構(gòu)建一個(gè)簡(jiǎn)單的 Hello World 工程。不要太關(guān)注代碼的細(xì)節(jié),后面將會(huì)進(jìn)行詳細(xì)介紹。代碼如下:
var express = require("express");? #A ? var app = express();? #B ? app.get("/", function(request, response) {? #C ? response.send("Hello world!");??????????? #C });???????????????????????????????????????? #C ? app.listen(3000, function() {??????????????????? ???#D ? console.log("Express app started on port 3000."); #D });???????????????????????????????????????????????? #D
A:導(dǎo)入 express 模塊并新建變量。
B:創(chuàng)建 app 應(yīng)用
C:設(shè)置訪問(wèn) Root 路由,并將響應(yīng)設(shè)置為 “Hello world!”。
D:設(shè)置程序監(jiān)聽(tīng)的端口,并打贏服務(wù)啟動(dòng)成功的信息。
再次提醒一下,沒(méi)有全部弄懂代碼不要緊,后面會(huì)有更詳細(xì)的講解。
你馬上就能學(xué)到關(guān)于 Express 的所有知識(shí)了。
小結(jié)本文主要介紹了:
Node.js 可以編寫(xiě) Web 應(yīng)用,但是開(kāi)發(fā)過(guò)程并不高效。而 Express 則優(yōu)雅的解決了這些問(wèn)題。
Express 很小但是也非常靈活
Express 有幾個(gè)關(guān)鍵特性:
中間件將程序處理進(jìn)行了拆分并且按照順序鏈?zhǔn)綀?zhí)行。
路由同樣對(duì)程序進(jìn)行了拆分,按規(guī)則對(duì)不同的訪問(wèn)請(qǐng)求做出不同的響應(yīng)。
子工程可以實(shí)現(xiàn)對(duì)大型 Express 的拆分,從而提高可讀性方便后期維護(hù)。
Express 中的代碼大多請(qǐng)求處理函數(shù)的編寫(xiě),而 Express 為此提供了大量易用 API 。
原文地址
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/84828.html
摘要:編程書(shū)籍的整理和收集最近一直在學(xué)習(xí)深度學(xué)習(xí)和機(jī)器學(xué)習(xí)的東西,發(fā)現(xiàn)深入地去學(xué)習(xí)就需要不斷的去提高自己算法和高數(shù)的能力然后也找了很多的書(shū)和文章,隨著不斷的學(xué)習(xí),也整理了下自己的學(xué)習(xí)筆記準(zhǔn)備分享出來(lái)給大家后續(xù)的文章和總結(jié)會(huì)繼續(xù)分享,先分享一部分的 編程書(shū)籍的整理和收集 最近一直在學(xué)習(xí)deep learning深度學(xué)習(xí)和機(jī)器學(xué)習(xí)的東西,發(fā)現(xiàn)深入地去學(xué)習(xí)就需要不斷的去提高自己算法和高數(shù)的能力然后...
摘要:前端日?qǐng)?bào)精選和實(shí)現(xiàn)直接當(dāng)前頁(yè)預(yù)覽手淘互動(dòng)動(dòng)效的探索白話原型和原型鏈源碼解析瀏覽器前端優(yōu)化中文第期深入理解中的動(dòng)畫(huà)演示,提高你的網(wǎng)頁(yè)開(kāi)發(fā)技能知乎專欄實(shí)戰(zhàn)一概覽工作機(jī)制第部分迷津欲有問(wèn)把賣了眾成翻譯代理程序?qū)崿F(xiàn)復(fù)制集搭建及抓包 2017-08-24 前端日?qǐng)?bào) 精選 iframe和HTML5 blob實(shí)現(xiàn)JS,CSS,HTML直接當(dāng)前頁(yè)預(yù)覽手淘互動(dòng)動(dòng)效的探索白話原型和原型鏈React 源碼解...
閱讀 2702·2021-11-22 15:24
閱讀 1440·2021-11-17 09:38
閱讀 2827·2021-10-09 09:57
閱讀 1265·2019-08-30 15:44
閱讀 2507·2019-08-30 14:00
閱讀 3614·2019-08-30 11:26
閱讀 2995·2019-08-29 16:28
閱讀 834·2019-08-29 13:56