Express 實戰(一):概覽

2017-08-13-Cover

在正式學習 Express 內容以前,咱們有必要從大的方面瞭解一下 Node.js 。html

在很長的一段時間裏,JavaScript 一門編寫瀏覽器中運行腳本的語言。不過近些年,隨着互聯網的發展以及技術進步,JavaScript 迎來了一個集中爆發的時代。一個標準性的事件就是 09 年 Node.js 的橫空出世。前端

Node.js 由 Google Chrome 的 V8 引擎發展而來,它可以讓 JavaScript 運行在服務端。從而極大的拓展了 JavaScript 的應用場景也讓 JavaScript 全棧成爲了一個熱門話題。開發者沒必要再去學習 Ruby、Python、Java 等語言和框架,僅僅依靠 JavaScript 就能完成先後端的大部分開發任務。node

<!--more-->python

雖然,從某些方面來講 JavaScript 並不完美甚至還有一些設計缺陷,可是這並不影響 Nodejs 的流行。V8 引擎快速處理能力和異步編程風格,讓開發者從多線程中解脫了出來。其中,先後端同一技術棧能夠說是它最大的殺手鐗。而日益豐富的生態環境也讓 JavaScript 受到開發者愈來愈多的關注,使用 Node.js 進行開發也變成了一件很是符合潮流的事情了。程序員

和瀏覽器環境中的 JavaScript 同樣,Node.js 也只提供了構建應用基本所需的底層接口和特性。而這些底層接口通常都很冗長、難用。因此有人就在 Node.js 的基礎上實現了 Express 框架。其基本理念與 jQuery 相似,經過對底層接口進行了封裝,在簡化代碼的同時提供更高級的接口。另外,Express 拓展性也很是強。框架自己與程序的架構和業務無關,而且你還能夠經過第三方庫進行功能拓展。數據庫

Node.js 應用場景

Node.js (一般簡稱爲 Node )是一個 JavaScript 代碼的運行平臺。雖然大多數情形下 JavaScript 都運行在瀏覽器中,可是並無任何地方規定其只能運行在瀏覽器中。做爲一門編程語言,本質上它與 Ruby、Python、C++、PHP 並無什麼區別。就像你可使用 python myfile.py 來運行 Python 腳本,你可使用  node myfile.js 來執行 JavaScript 程序。express

可是 Node 到底有啥優勢值得咱們在服務端開發是嘗試呢?npm

首先,Node.js 的 JavaScript 引擎很是快。畢竟,它是基於以速度著稱的 Google Chrome V8 引擎,能夠每秒執行幾千條 JavaScript 指令。編程

其次,Node.js 經過異步編程範式將其高併發的能力發揮的淋漓盡致。後端

用現實生活中的烘焙作類比最恰當不過了。假設如今我須要製做一些鬆餅,那麼首先就須要把麪粉弄好。而此時我是沒法抽身作其餘的事情的。可是,一旦我把鬆餅送進烤箱,我就能夠抽身作其餘的事情而沒必要乾等。

在 Node.js 中,客戶端可能隨時都會給服務端發送請求。有可能在你處理一個請求時,另外一個請求也被客戶端送達了。假設,兩個請求都須要訪問數據庫。那麼就能夠在第一個請求進行數據庫操做時,轉去處理第二個請求。雖然不能同時對二者作成響應,可是咱們可使用異步方式跳過對耗時操做結果的等待直接處理後續請求。而其餘的一些運行環境默認是沒有此能力的。例如,Ruby on Rails 同時時間只能處理一個請求。若是想提升程序的併發能力,那麼你就須要去購買更多的服務器。

下圖能夠清晰的看出二者的區別:

01_01

與同步方式相比,異步處理的效率明顯要更高,雖然異步代碼也不是並行處理。

固然,這並非說異步處理機制讓 Node.js 是世界上最快的語言之一。Node.js 雖然可以最大化壓制單核 CPU 的性能,可是仍是沒法與多核處理能力相媲美。其餘語言中可讓你利用多核能力同時執行多個任務。像以前和烘培同樣:你能夠購買更多的烤箱來同時烤更多的餅乾。Node 正在開始支持這個能力,可是它並不像其餘語言中那樣重要。

就我我的而言,由於性能而選擇 Node.js 並非最重要的依據,雖然,它確實比 Ruby、Python 等腳步語言要快。最大的理由是,它在先後端開發中使用同一種語言。

一般,在編寫 Web 應用程序時你都會要使用 JavaScript。可是在 Node.js 出現以前,先後端的開發必須使用不一樣的語言進行。爲此你須要學習多種的語言和框架。有了 Node.js 以後,你就可使用一門語言在先後端開發中自由切換,這是最吸引人的地方。

什麼是 Express ?

Express 是一個基於 Node.js 封裝的上層服務框架,它提供了更簡潔的 API 更實用的新功能。它經過中間件和路由讓程序的組織管理變的更加容易;它提供了豐富的 HTTP 工具;它讓動態視圖的渲染變的更加容易;它還定義了一組可拓展標準。

Node.js 的功能

經過一個簡單的 JavaScript 函數,你就能夠利用 Node.js 建立一個 Web 程序。該函數用於監聽來自瀏覽器或者其餘設備的發起的網絡請求。當接收到一個請求後,函數會分析請求的內容並作成相應的處理。例如,當你請求站點主頁時,該函數就會知道知道你的目的並將主頁的 HTML 渲染出來。若是是請求某個 API 接口,該函數就會把對應的 JSON 數據返回給客戶端。

假設,如今須要服務器返回當前時間和時區信息給用戶,那麼該程序大體包括以下功能:

  • 若是客戶端發起主頁請求,Web 應用將會返回一個包含所需信息的 HTML 。
  • 若是客戶端訪問地址錯誤,Web 應用將會返回 HTTP 404 錯誤,並附帶一段錯誤描述。

若是直接在 Node.js 之上構建該應用而不使用 Express 的話,那麼完整流程圖大抵以下:

01_02

在上述流程中,開發人員只須要關注圓圈部份內容處理。

這個用於處理瀏覽器請求的 JavaScript 函數叫作請求處理函數(request handler)。它也僅僅是一個處理請求並做出響應的 JavaScript 函數,並沒有任何特殊之處。Node.js 的 HTTP 服務會接管其中的網絡鏈接,因此你無需關注和處理複雜的網絡協議內容。

從代碼角度來講,該函數包含兩個參數:一個是網絡請求 request 對象 ,另外一個表示網絡響應的 response 對象。在前面時間信息應用中,該請求處理函數會檢查請求 URL 。若是請求的是主頁,那麼就返回成功的響應頁面。不然,返回 404 錯誤。沒有 Node.js 應用中都是這麼處理的:編寫處理函數對請求做出響應,很是的簡單。

問題在於,Node.js 的 API 對開發者來講並非很是友好。例如,若是咱們想發送一個 JPEG 圖片的話,可能須要至少 45 行代碼才行。建立可複用 HTML 模版則更復雜。另外,Node.js 的 HTTP 模塊雖然強大,可是仍然缺乏一些實用特性。

Express 的出現就是爲了解決這些問題,讓你可以高效的使用 Node.js 來編寫 Web 應用。

Express 給 Node.js 帶來了什麼?

從大的方面來講,Express 爲 Node.js 的 HTTP 模塊帶來了兩大特性:

  • 經過提供大量易用接口,簡化了程序的複雜度。例如上面放鬆 JPEG 圖片問題,Express 能夠將代碼壓縮帶一行。
  • 它容許對請求處理函數進行拆分,將其重構爲不少負責特定請求的小型請求處理函數。這便於模塊化和後期維護。

與上圖相比,下圖是 Express 處理請求的大體流程:

01_03

與以前同樣,開發者只須要關注圓圈部分的內容。

雖然,圖看起來比前面複雜,可是實際開發卻更簡單,本質上它主要作了兩件事:

  1. 與以前一個大型的 request 請求處理函數不一樣,這裏使用大量小型處理函數。有些函數每次都會執行(例如,請求日誌),而有些函數只在特定情形下才會觸發(例如,404 錯誤)。Express 有不少使用的工具可以對這些處理函數進行區分。
  2. 請求處理函數中有兩個參數:request 和 response。Node 的 HTTP 能夠對其作些基本處理,例如:獲取瀏覽器的 user-agent 。Express 則更爲強大,你能夠獲取到訪問者 IP 地址,以及解析優化過的 URL 請求對象。esponse 對象也一樣獲得了加強。經過相似 sendFile 這樣的函數將文件傳輸代碼壓縮至一行。這極大的簡化了處理函數的功能實現。

利用 Express 提供的簡潔 API 接口,經過編寫小型 request 請求處理函數,能夠極大的壓縮代碼量提升開發效率。

Express 的最小化理念

雖然 Express 是一個框架,可是它的編程規範很是靈活。你能夠用它編寫各類類型的應用,從視頻聊天到我的博客等等。另外,Express 自己並非百寶箱,你可能會在實際開發中須要使用大量第三方類庫。這些類庫能幫你解決一些次要問題,這樣你能夠將關注點地放在那些重要的問題上,而後發揚 Unix do-one-thing-well 的哲學將事情處理好。

可是這種最小化理念也是一把雙刃劍。一方面,Express 很是靈活可靠,並且不會引入那些無用的垃圾代碼。另外一方面,與其餘框架相比這種簡潔不可避免致使了部分功能缺失。這意味須要在程序架構上作更多的功課,而且在出現問題後要花時間去尋找第三方模塊。離開箱即用還差一點。

有人喜歡靈活多變的框架,而有人則喜歡那些結構固定的框架。例如,PayPal 雖然也使用 Express,可是卻制定了嚴格的規範來約束其開發者。Express 自己並不關注程序架構,因此程序員能夠根據偏好自行選擇。因爲對程序有着絕對控制權,因此一旦你作出不明智的決策,那麼後面的坑你就慢慢爬吧。

對於大型框架和極簡框架的優劣,歷來都沒有固定的正確答案,因此咱們無須太過糾結。這裏,我只但願你記住 Express 是一個極簡框架。

Express 的核心

Express 很是簡潔並且對 Node.js 的封裝效果也很是棒,而這一切都源於框架中的四個設計。

中間件

正如以前提到的,原生的 Node.js 使用一個 request 處理函數應對全部請求並作出響應。

Middleware 這個名字起的並很差,可是這個術語並非 Express 獨有,相反它已經存在好久了。概念很是簡單:咱們不採用一個巨大的 request 請求處理函數,相反咱們將一系列簡單的處理函數組合起來。每個小的處理函數對應一個小任務,而這些處理函數就被稱爲中間件。

中間件能夠處理各類任務,從記錄請求到發送靜態文件到設置 HTTP 頭部。例如,應用中使用的第一個中間件功能可能就是記錄服務器中每一個請求的 logger-log。當日志記錄完成後,它將繼續執行調用鏈中的下一個中間件。而下一個中間件功能可能會去驗證用戶。若是權限不夠,就會使用「未受權」進行提示。反之則繼續執行下一個中間件。此時中間件功能可能會是渲染主頁並結束響應。下圖演示了這兩種情形:

01_04

在圖中能夠看出,記錄日誌的中間件位於第一個而且確定會被執行。緊接着就是執行權限認證的中間件。若是用戶權限知足的話就繼續執行下一個中間件,不然就再也不執行後續中間件。

中間件最大的特色就是其相對來講比較標準,這也意味着開發者能夠經過爲 Express 開發中間件來拓展其功能。同時,這也許意味着某些通用的中間件,頗有可能已經有人開發過來,例如: LESS 和 SCSS 等靜態文件的編譯、權限控制、cookies 和 sessions 的解析。

路由

相比中間件,Routing 顯然更好。與中間價相似,路由對請求處理函數進行了拆分。不一樣的是,路由根據請求的 URL 和 HTTP 方法來決定處理方式的。

例如,你的程序中有一個主頁和一個留言板頁面。當用戶使用 GET 去請求主頁時,Express 會返回對應的主頁內容。對留言板的請求的處理也是如此。若是用戶經過 POST 方法在留言板頁面中進行了留言操做的話,路由須要作出對應處理並刷新頁面。

相似於中間件,上述路由的處理也是經過處理函數進行定義的。而不一樣的行爲會調用不一樣的處理函數。

Express 中的中間件和路由相輔相成。例如:你能夠一邊記錄請求日誌,同時對主頁路由作出響應。

子應用

Express 應用一般都很小,甚至能夠是一個文件。隨着應用規模的擴張,可能你會將其進行拆分爲多個文件和文件夾。雖然 Express 對應用的規模增加沒有明確的指導規則。可是咱們能夠經過 sub-applications 這一重要特性來做出應對。 在 Express 術語中這些只應用也被稱爲路由器

經過實現正常規模的路由器子應用,能夠將一個大型應用進行模塊拆分。甚至你能夠對某些子應用進行更細緻的拆分。例如,在應用中可能存在管理後臺、單頁應用、API 接口 等等幾個子模塊。這時,你就能夠將這些子模塊做爲一個子應用來實現。詳情以下:

01_05

當程序規模變大以後,該特性的優點將會逐步凸顯出來。

易用的 API 函數

Express 由中間件和路由構成,在其中你須要編寫大量的異步處理函數來實現相關功能。

爲了使處理過程更加高效正確,Express 在原生的 Node.js 基礎上進行了大量的封裝。在壓縮代碼量提升效率的同時也下降了人爲錯誤的機率。除了發送文件以外,Express 提供的 HTML 渲染功能也讓原生 Node.js 可望不可即。另外在請求解析方面,Express 也作了很是多的工做。

跟前面的特性不同的是,在保持功能強大的同時這些易用的函數並不會對應用形成負面影響。

Express 生態環境

像其餘的工具同樣,Express 並非遺世獨立的。

它存活於 Node.js 的生態中,全部你能找到大量的第三發模塊提高你的開發效率,例如數據庫鏈接驅動。由於Express 可拓展性極強,全部整個生態中存在大量爲 Express 開發的類庫。

Express 跟其餘框架的比較

Express 既不是第一個 Web 框架,固然更不會是最後一個。

一樣,Express 也不是 Node.js 生態中的惟一框架。可能它最大的競爭對手就是 Hapi.js 了。與 Express 相似,它也有路由、中間件這就概念。不過不一樣的是它沒有基於 Node.js 的 HTTP 模塊來處理網絡請求,而是有 Walmart 開發的網絡模塊。該模塊被 Mozilla,OpenTable 和 NPM 所接受並在真實程序中檢驗過。做爲 Express 的最大競爭對手,所以我懷疑雙方的開發人員可能彼此抱有不小敵意。

在 Node.js 世界中最流行的大型框架非全棧式的 Meteor 莫屬。相比自由靈活的 Express ,Metero 有着很是嚴格的程序結構。不一樣於 Express 只關注 HTTP 層的處理,Meteor 做爲全棧框架能夠同時運行在客戶端和服務端。固然,這僅僅只是設計上的選擇說不上到底誰更優秀。

跟 Express 基於 Node.js 進行封裝相似,也有人對 Express 進行更高級的封裝。例如,PayPal 創造的 Kraken 。儘管從技術角度來講,Kraken 不過只是 Express 的一箇中間件而已。可是,它仍是作了很多的事情,例如:中間件的安全綁定。Sails.js 則是另外一個以 Express 爲基礎的新型框架,它內置了數據庫、WebSocket 集成、API 生產等等功能。全部的這些框架,都是 Express 的一種相對固定化的封裝實現。

Express 最主要的幾個特性之一就是中間件。Connect 是一個僅做用於 Node.js 和中間件的框架。它沒有提供路由和易用函數接口。而 Express 曾經在它的中間件層中使用了 Connect。雖然如今被拋棄了,可是 Express 中間件一直都徹底兼容 Connect 中間件。這意味着 Express 的火力獲得了更大的提高。

除了上面提到的這些,還有不少使用其它語言實現的 Web 框架。

Express 的不少靈感都來自於 Ruby 世界中的輕型 Web 框架 Sinatra。與 Express 相似,Sinatra 中也有路由和中間件功能。Sinatra 框架思想被其餘不少語言所借鑑而且從新實現,若是你曾經用過這類框架的話,那麼對 Express 必定不會陌生。固然,Express 也借鑑了 Python 中的 Bottle 和 Flask 框架。

相應的,Express 與 Django、Ruby on Rails、ASP.NET 等框架差距巨大。這些框架都十分龐大,並且程序結構也相對固定功能更爲豐富。並且,Express 與 PHP 也差別明顯,雖然都是運行在服務上可是後者與 HTML 緊耦合。

Express 僅僅是服務端 Web 框架中的一種,因此咱們不能在這裏說 Express 就必定比其餘的框架好。它具有一些獨有的特性,例如,Node.js 的性能以及先後端統一的語言。可是與之同時,它的功能遠比其餘框架來的少而去 JavaScript 也並非一門獲得廣大開發者承認的「好」語言。脫離具體場景討論優劣勢沒有意義的,下面咱們就看看 Express 一些適用場景。

Express 的應用場景

理論上來講,Express 能夠用來構建任何 Web 應用。對全部請求做出響應這件事上述提到的框架一樣可以作到。因此,爲何要選擇 Express 呢?

最大的優勢就是 Node.js 中編寫的 JavaScript 能夠在瀏覽器和客戶端實現共享。從代碼複用角度來講,這種狀況是最理想的。從心理角度來講也很是有用,開發過程當中無需進行服務器模式和客戶端模式的切換。前端開發者能夠在不學習新語言的狀況下直接就能夠編寫後端代碼。固然,前端開發者仍是須要學習一些新內容的,否則這本書就沒存在的必要了。

Express 能夠幫助你作到這一點,人們已經爲這個技術棧擬好了名稱:MEAN 。像 「LAMP」 表明 Linux、Apache、MySQL 和 PHP 同樣,「MEAN」 表示 MongoDB、Express、Angular 和 Node.js。人們之因此對它喜好有加是由於它是純 JavaScript 技術棧。

Express 經常使用於驅動單頁應用程序(SPA)。SPA 在前端重度依賴 JavaScript,並且一般須要一個服務器組件。大多數服務器只須要簡單的提供 HTML、CSS 和 JavaScript ,可是有時候 REST API 也是常規需求。Express 能夠同時完成這兩件任務,既能夠提供 HTML 也很是適合構建 API 。 Express 相對較低的學習曲線使得前端開發者在幾乎無需學習新內容的狀況下搭建一個 SPA 服務。

當你使用 Express 編寫應用的時候就決定了你必須使用 MEAN 技術棧中的 E 和 N 部分,而對於另外兩個 Express 沒有作出過限定你徹底能夠採用不一樣的方案。例如,可使用 Backbone.js 替換其中的 Angular,構成 MEBN 技術棧。使用 SQL 替換 MongoDB 構成 SEAN 技術棧。雖然 MEAN 術語很常見並且配置也很是流行,可是你徹底能夠更具須要自行選擇。在這本書中咱們將涵蓋的技術棧是 MEN:MongoDB、Express 和 Node.js。

另外 Express 還具備一些實時特性。雖然其餘語言也支持 WebSocket 和 WebRTC,可是 Node.js 彷佛要更強。這意味着你能夠將這些特性應用到 Express 程序中。由於 Node.js 能作的,Express 同樣很多。

Node.js 和 Express 的第三方模塊

社區中存在大量能夠在 Express 中使用的模塊。有一些是 Express 獨佔的,這些模塊與路由和中間件的特性高度兼容。其餘的非獨佔模塊也能提高 Express 應用的開發體驗和程序性能。

若是你曾經有過 ERB、Jinja二、HAML 等模版引擎的使用經驗的話,你就會發現 Express 自帶的功能在渲染 HTML 方面簡直就是弱雞。好在 Express 還可使用 EJS 和 Jade 這些社區模版引擎來解決這個問題。

另外,Express 自己並無對數據庫作支持。你能夠經過文件、關係數據庫、或者其餘機制來實現數據保存。不事後面將會介紹在 Express 中如何經過 Mongoose 來調用 MongoDB 數據庫。

須要注意的一點是:並不存在 Express 模塊這一律念,因此第三方庫都是 Node.js 模塊。Node.js 模塊與 Express 相互兼容而且可以配合其工做。全部這些某塊都是在 npm 倉庫註冊的 JavaScript 代碼塊,而且可使用一致的方法進行安裝。與其餘環境中同樣,模塊之間能夠相互依賴,而且不一樣模塊能夠相互配合。另外,Express 也不過是 Node.js 中的一個模塊而已。

Hello World

每次學習新內容的時候,絕大多數都是從 Hello World 開始。

那麼如今咱們來看看如何使用 Express 構建一個簡單的 Hello World 工程。不要太關注代碼的細節,後面將會進行詳細介紹。代碼以下:

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:導入 express 模塊並新建變量。
B:建立 app 應用
C:設置訪問 Root 路由,並將響應設置爲 「Hello world!」。
D:設置程序監聽的端口,並打贏服務啓動成功的信息。

再次提醒一下,沒有所有弄懂代碼沒關係,後面會有更詳細的講解。

你立刻就能學到關於 Express 的全部知識了。

小結

本文主要介紹了:

  • Node.js 能夠編寫 Web 應用,可是開發過程並不高效。而 Express 則優雅的解決了這些問題。
  • Express 很小可是也很是靈活
  • Express 有幾個關鍵特性:
  • 中間件將程序處理進行了拆分而且按照順序鏈式執行。
  • 路由一樣對程序進行了拆分,按規則對不一樣的訪問請求作出不一樣的響應。
  • 子工程能夠實現對大型 Express 的拆分,從而提升可讀性方便後期維護。
  • Express 中的代碼大多請求處理函數的編寫,而 Express 爲此提供了大量易用 API 。

原文地址

相關文章
相關標籤/搜索