Express/Node 簡介
在第一篇 Express 文章中,我們回答了“什麼是 Node?”和“什麼是 Express?”的問題,並概述了 Express Web 框架的獨特之處。我們將概述主要功能,並向您展示 Express 應用程式的主要構建塊(儘管此時您還沒有開發環境來對其進行測試)。
| 先決條件 | 對 伺服器端網站程式設計 有基本的瞭解,尤其是對 網站中的客戶端-伺服器互動 的機制。 |
|---|---|
| 目標 | 熟悉 Express 是什麼以及它如何在 Node 中發揮作用,它提供了哪些功能,以及 Express 應用程式的主要構建塊。 |
介紹 Node
Node(或更正式地說,Node.js)是一個開源、跨平臺的執行時環境,允許開發人員使用 JavaScript 建立各種伺服器端工具和應用程式。執行時旨在在瀏覽器上下文之外使用(即直接在計算機或伺服器作業系統上執行)。因此,該環境省略了瀏覽器特定的 JavaScript API,並添加了對更傳統的作業系統 API 的支援,包括 HTTP 和檔案系統庫。
從 Web 伺服器開發的角度來看,Node 具有許多優勢
- 效能出色!Node 被設計為最佳化 Web 應用程式的吞吐量和可擴充套件性,並且是許多常見 Web 開發問題的良好解決方案(例如即時 Web 應用程式)。
- 程式碼是用“純 JavaScript”編寫的,這意味著在編寫客戶端和伺服器端程式碼時,您將花費更少的時間處理語言之間的“上下文切換”。
- JavaScript 是一種相對較新的程式語言,與其他傳統 Web 伺服器語言(如 Python、PHP 等)相比,它受益於語言設計方面的改進。許多其他新興的流行語言會編譯/轉換為 JavaScript,因此您也可以使用 TypeScript、CoffeeScript、ClojureScript、Scala、LiveScript 等。
- Node 包管理器 (npm) 提供對數十萬個可重用包的訪問。它還具有最佳的依賴關係解析功能,並且還可以用於自動化大多數構建工具鏈。
- Node.js 是可移植的。它可在 Microsoft Windows、macOS、Linux、Solaris、FreeBSD、OpenBSD、WebOS 和 NonStop OS 上使用。此外,它得到了許多 Web 託管提供商的良好支援,這些提供商通常會提供用於託管 Node 網站的特定基礎設施和文件。
- 它擁有非常活躍的第三方生態系統和開發人員社群,並且有很多人願意提供幫助。
您可以使用 Node.js 建立一個使用 Node HTTP 包的簡單 Web 伺服器。
Hello Node.js
以下示例建立了一個 Web 伺服器,該伺服器監聽 URL http://127.0.0.1:8000/ 上的任何型別的 HTTP 請求 - 當收到請求時,指令碼將響應字串:“Hello World”。如果您已經安裝了 node,您可以按照以下步驟嘗試該示例
- 開啟終端(在 Windows 上,開啟命令列工具)
- 建立您要儲存程式的資料夾,例如,
test-node,然後透過在終端中輸入以下命令來進入它bashcd test-node - 使用您喜歡的文字編輯器,建立一個名為
hello.js的檔案,並將以下程式碼貼上到其中js// Load HTTP module const http = require("http"); const hostname = "127.0.0.1"; const port = 8000; // Create HTTP server const server = http.createServer(function (req, res) { // Set the response HTTP header with HTTP status and Content type res.writeHead(200, { "Content-Type": "text/plain" }); // Send the response body "Hello World" res.end("Hello World\n"); }); // Prints a log once the server starts listening server.listen(port, hostname, function () { console.log(`Server running at http://${hostname}:${port}/`); }); - 將檔案儲存在您上面建立的資料夾中。
- 返回終端並輸入以下命令bash
node hello.js
最後,在 Web 瀏覽器中導航到 https://:8000;您應該在空白網頁的左上角看到文字“Hello World”。
Web 框架
Node 本身並不直接支援其他常見的 Web 開發任務。如果您想為不同的 HTTP 動詞(例如 GET、POST、DELETE 等)新增特定處理,分別處理不同 URL 路徑(“路由”)上的請求,提供靜態檔案,或使用模板動態建立響應,那麼 Node 本身將無濟於事。您要麼需要自己編寫程式碼,要麼可以避免重新發明輪子並使用 Web 框架!
介紹 Express
Express 是最流行的 Node.js Web 框架,是許多其他流行的 Node.js 框架的底層庫。它提供機制來
- 為不同 URL 路徑(路由)上具有不同 HTTP 動詞的請求編寫處理程式。
- 與“檢視”渲染引擎整合,以便透過將資料插入模板來生成響應。
- 設定常見的 Web 應用程式設定,例如用於連線的埠和用於渲染響應的模板位置。
- 在請求處理管道中的任何點新增額外的請求處理“中介軟體”。
雖然Express 本身相當簡約,但開發人員建立了相容的中介軟體包來解決幾乎所有 Web 開發問題。有用於處理 cookie、會話、使用者登入、URL 引數、POST 資料、安全標頭以及許多其他內容的庫。您可以在 Express 中介軟體(以及一些流行的第三方包的列表)中找到由 Express 團隊維護的中介軟體包列表。
注意:這種靈活性是一把雙刃劍。有中介軟體包可以解決幾乎所有問題或需求,但找出要使用的正確包有時可能是一個挑戰。也沒有“正確的方法”來構建應用程式,而且您在網際網路上找到的許多示例都不是最佳的,或者只顯示了您為了開發 Web 應用程式而需要做的事情的一小部分。
Node 和 Express 來自哪裡?
Node 和 Express 的流行程度如何?
Web 框架的流行程度很重要,因為它表明它是否會繼續得到維護,以及在文件、附加庫和技術支援方面可能會提供哪些資源。
沒有現成的、確定的伺服器端框架流行程度衡量標準(儘管您可以使用一些機制來估計流行程度,例如計算每個平臺的 GitHub 專案和 StackOverflow 問題的數量)。一個更好的問題是,Node 和 Express 是否“足夠流行”以避免不受歡迎平臺的問題。它們是否在不斷發展?如果您需要幫助,您可以獲得幫助嗎?如果您學習 Express,您是否有機會獲得報酬的工作?
基於使用 Express 的高知名度公司的數量、貢獻程式碼庫的人數以及提供免費和付費支援的人數,答案是肯定的,Express 是一個流行的框架!
Express 是有意見的框架嗎?
Web 框架通常將自己稱為“有主見”或“無主見”。
有主見框架是對“正確方法”處理任何特定任務有主見的框架。它們通常支援在特定領域(解決特定型別的問題)中快速開發,因為通常對做任何事情的正確方法都有很好的理解和記錄。但是,它們在解決其主要領域之外的問題時可能不太靈活,並且往往在元件和方法的選擇方面提供更少的選擇。
相反,無主見框架對將元件粘合在一起以實現目標的最佳方式,甚至對應該使用哪些元件,都沒有太多限制。它們使開發人員更容易使用最合適的工具來完成特定任務,儘管代價是您需要自己找到這些元件。
Express 是無主見的。您可以在請求處理鏈中插入幾乎所有相容的中介軟體,並且可以按您喜歡的任何順序插入。您可以將應用程式構建在一個檔案或多個檔案中,並使用任何目錄結構。您有時可能會覺得您有太多選擇!
Express 程式碼長什麼樣?
在傳統的基於資料的網站中,Web 應用程式會等待來自 Web 瀏覽器(或其他客戶端)的 HTTP 請求。收到請求後,應用程式會根據 URL 模式以及可能包含在 POST 資料或 GET 資料中的相關資訊來確定需要什麼操作。根據需要,它可能會讀取或寫入資料庫資訊或執行滿足請求所需的 other 任務。然後,應用程式將返回一個響應到 Web 瀏覽器,通常透過將檢索到的資料插入 HTML 模板中的佔位符來動態建立瀏覽器要顯示的 HTML 頁面。
Express 提供方法來指定特定 HTTP 動詞(GET、POST、PUT 等)和 URL 模式(“路由”)呼叫哪個函式,以及方法來指定使用哪個模板(“檢視”)引擎、模板檔案的位置以及要使用哪個模板來渲染響應。您可以使用 Express 中介軟體來新增對 cookie、會話和使用者、獲取 POST/GET 引數等的支援。您可以使用 Node 支援的任何資料庫機制(Express 不定義任何與資料庫相關的行為)。
以下部分解釋了使用Express 和Node 程式碼時會看到的一些常見內容。
Helloworld Express
首先,讓我們考慮標準的 Express Hello World 示例(我們將在下面以及接下來的部分中討論此示例的各個部分)。
注意:如果您已經安裝了 Node 和 Express(或者按照 下一篇文章 中的說明安裝它們),您可以在一個名為 app.js 的文字檔案中儲存此程式碼,然後透過呼叫以下命令在 bash 命令提示符中執行它
node ./app.js
const express = require("express");
const app = express();
const port = 3000;
app.get("/", function (req, res) {
res.send("Hello World!");
});
app.listen(port, function () {
console.log(`Example app listening on port ${port}!`);
});
前兩行 require()(匯入) express 模組並建立一個 Express 應用程式。這個物件通常命名為 app,它具有用於路由 HTTP 請求、配置中介軟體、渲染 HTML 檢視、註冊模板引擎以及修改 應用程式設定 的方法,這些設定控制應用程式的行為(例如環境模式、路由定義是否區分大小寫等)。
程式碼的中間部分(從 app.get 開始的三行)顯示了一個路由定義。app.get() 方法指定了一個回撥函式,每當有 HTTP GET 請求且路徑('/')相對於網站根目錄時,就會呼叫該函式。回撥函式將請求和響應物件作為引數,並在響應上呼叫 send() 以返回字串“Hello World!”。
最後一塊程式碼在指定埠 ('3000') 上啟動伺服器,並在控制檯中列印一條日誌註釋。在伺服器執行後,您可以在瀏覽器中訪問 localhost:3000 以檢視返回的示例響應。
匯入和建立模組
模組是一個 JavaScript 庫/檔案,您可以使用 Node 的 require() 函式將其匯入到其他程式碼中。Express 本身就是一個模組,我們使用在 Express 應用程式中的中介軟體和資料庫庫也是模組。
以下程式碼展示了我們如何使用名稱匯入模組,以 Express 框架為例。首先,我們呼叫 require() 函式,指定模組名稱為字串 ('express'),並呼叫返回的物件來建立一個 Express 應用程式。然後,我們可以訪問應用程式物件的屬性和函式。
const express = require("express");
const app = express();
您也可以建立自己的模組,這些模組可以以相同的方式匯入。
注意: 您會想要建立自己的模組,因為這使您可以將程式碼組織成可管理的塊——單一檔案的整體應用程式很難理解和維護。使用模組也有助於管理名稱空間,因為只有您顯式匯出的變數才會在使用模組時匯入。
要使物件在模組外部可用,您只需要將它們作為 exports 物件上的附加屬性公開。例如,下面的 square.js 模組是一個匯出 area() 和 perimeter() 方法的檔案
exports.area = function (width) {
return width * width;
};
exports.perimeter = function (width) {
return 4 * width;
};
我們可以使用 require() 匯入此模組,然後呼叫匯出的方法,如下所示
const square = require("./square"); // Here we require() the name of the file without the (optional) .js file extension
console.log(`The area of a square with a width of 4 is ${square.area(4)}`);
注意: 您還可以指定模組的絕對路徑(或名稱,如我們最初所做的那樣)。
如果您想在一個賦值中匯出一個完整的物件,而不是逐個屬性地構建它,請將其分配給 module.exports,如下所示(您也可以這樣做,以使匯出的物件的根成為建構函式或其他函式)
module.exports = {
area(width) {
return width * width;
},
perimeter(width) {
return 4 * width;
},
};
注意: 您可以將 exports 視為對 module.exports 的 快捷方式,在給定的模組中。實際上,exports 只是一個變數,它在模組被評估之前被初始化為 module.exports 的值。該值是對一個物件的引用(在這種情況下為空物件)。這意味著 exports 持有對 module.exports 引用的相同物件的引用。這也意味著,透過將另一個值分配給 exports,它不再繫結到 module.exports。
有關模組的更多資訊,請參閱 Modules(Node API 文件)。
使用非同步 API
JavaScript 程式碼經常使用非同步 API 而不是同步 API 來執行可能需要一些時間才能完成的操作。同步 API 是指每個操作必須在下一個操作開始之前完成的 API。例如,以下日誌函式是同步的,並且會按順序(先,後)將文字列印到控制檯。
console.log("First");
console.log("Second");
相比之下,非同步 API 是指 API 將啟動一個操作並立即返回(在操作完成之前)。操作完成後,API 將使用某種機制執行其他操作。例如,下面的程式碼將打印出“後,先”,因為即使 setTimeout() 方法首先呼叫並立即返回,操作也不會在幾秒鐘內完成。
setTimeout(function () {
console.log("First");
}, 3000);
console.log("Second");
在 Node 中,使用非阻塞非同步 API 比在瀏覽器中更重要,因為 Node 是一個單執行緒事件驅動的執行環境。“單執行緒”意味著對伺服器的所有請求都在同一執行緒上執行(而不是被生成到單獨的程序中)。這種模型在速度和伺服器資源方面非常高效,但這確實意味著,如果您的任何函式呼叫需要很長時間才能完成的同步方法,它們將不僅阻塞當前請求,還會阻塞您的 Web 應用程式處理的每個其他請求。
非同步 API 有多種方法可以通知您的應用程式它已完成。最常見的方法是在呼叫非同步 API 時註冊一個回撥函式,該函式將在操作完成時回撥。這是上面使用的做法。
注意: 如果您有一系列必須按順序執行的依賴非同步操作,使用回撥可能會很“混亂”,因為這會導致多級巢狀回撥。這個問題通常被稱為“回撥地獄”。可以透過良好的編碼實踐(參見 http://callbackhell.com/)、使用像 async 這樣的模組,或者將程式碼重構為原生 JavaScript 功能(如 Promises 和 async/await)來減少這個問題。Node 提供了 utils.promisify 函式以符合人體工程學地進行回撥 → Promise 轉換。
注意: Node 和 Express 的一個常見約定是使用錯誤優先回調。在此約定中,您的回撥函式中的第一個值是一個錯誤值,而後續引數包含成功資料。這篇文章很好地解釋了為什麼這種方法很有用:The Node.js Way - Understanding Error-First Callbacks(fredkschott.com)。
建立路由處理程式
在我們的 Hello World Express 示例(見上文)中,我們為 HTTP GET 請求定義了一個(回撥)路由處理程式函式,該函式指向站點根目錄 ('/')。
app.get("/", function (req, res) {
res.send("Hello World!");
});
回撥函式以請求和響應物件作為引數。在本例中,該方法在響應上呼叫 send() 以返回字串“Hello World!”。有很多 其他響應方法 用於結束請求/響應週期,例如,您可以呼叫 res.json() 傳送 JSON 響應,或者呼叫 res.sendFile() 傳送檔案。
注意: 您可以在回撥函式中使用任何您喜歡的引數名稱;當回撥被呼叫時,第一個引數始終是請求,第二個引數始終是響應。將它們命名為使您能夠在回撥的主體中識別您正在處理的物件是有意義的。
Express 應用程式物件還提供方法來為所有其他 HTTP 動詞定義路由處理程式,這些方法主要以完全相同的方式使用
checkout(), copy(), delete(), get(), head(), lock(), merge(), mkactivity(), mkcol(), move(), m-search(), notify(), options(), patch(), post(), purge(), put(), report(), search(), subscribe(), trace(), unlock(), unsubscribe()。
有一個特殊的路由方法 app.all(),它將在響應任何 HTTP 方法時被呼叫。這用於在特定路徑上為所有請求方法載入中介軟體函式。以下示例(來自 Express 文件)展示了一個處理程式,它將針對對 /secret 的請求執行,無論使用的是哪種 HTTP 動詞(只要它受 http 模組 支援)。
app.all("/secret", function (req, res, next) {
console.log("Accessing the secret section…");
next(); // pass control to the next handler
});
路由允許您匹配 URL 中的特定字元模式,並從 URL 中提取一些值,並將它們作為引數傳遞給路由處理程式(作為傳遞為引數的請求物件的屬性)。
通常,將特定站點部分的路由處理程式分組在一起並使用公共路由字首訪問它們很有用(例如,具有 Wiki 的站點可能在一個檔案中包含所有與 Wiki 相關的路由,並透過 /wiki/ 的路由字首訪問它們)。在 Express 中,這是透過使用 express.Router 物件實現的。例如,我們可以在名為 wiki.js 的模組中建立我們的 Wiki 路由,然後匯出 Router 物件,如下所示
// wiki.js - Wiki route module
const express = require("express");
const router = express.Router();
// Home page route
router.get("/", function (req, res) {
res.send("Wiki home page");
});
// About page route
router.get("/about", function (req, res) {
res.send("About this wiki");
});
module.exports = router;
注意: 向 Router 物件新增路由就像向 app 物件新增路由一樣(如前所述)。
要在我們的主應用程式檔案中使用路由器,我們將 require() 路由模組 (wiki.js),然後在 Express 應用程式上呼叫 use() 以將路由器新增到中介軟體處理路徑。然後,這兩個路由將可以透過 /wiki/ 和 /wiki/about/ 訪問。
const wiki = require("./wiki.js");
// …
app.use("/wiki", wiki);
我們將在連結部分 Routes and controllers 中向您展示更多關於使用路由的資訊,特別是關於使用 Router 的資訊。
使用中介軟體
中介軟體在 Express 應用程式中被廣泛使用,用於從提供靜態檔案到錯誤處理、壓縮 HTTP 響應等各種任務。路由函式透過向 HTTP 客戶端返回一些響應來結束 HTTP 請求-響應週期,而中介軟體函式通常對請求或響應執行一些操作,然後呼叫“堆疊”中的下一個函式,該函式可能是更多中介軟體或路由處理程式。中介軟體的呼叫順序由應用程式開發人員決定。
注意: 中介軟體可以執行任何操作,執行任何程式碼,對請求和響應物件進行更改,它也可以結束請求-響應週期。如果它沒有結束週期,那麼它必須呼叫 next() 以將控制權傳遞給下一個中介軟體函式(否則請求將被掛起)。
大多數應用程式都將使用第三方中介軟體來簡化常見的 Web 開發任務,例如處理 cookie、會話、使用者身份驗證、訪問請求 POST 和 JSON 資料、日誌記錄等。您可以在 Express 團隊維護的中介軟體包列表(其中還包括其他流行的第三方包)中找到這些包。其他 Express 包可在 npm 包管理器中獲得。
要使用第三方中介軟體,您首先需要使用 npm 將其安裝到您的應用程式中。例如,要安裝 morgan HTTP 請求記錄器中介軟體,您需要執行以下操作
npm install morgan
然後,您可以在 Express 應用程式物件上呼叫 use() 將中介軟體新增到堆疊中
const express = require("express");
const logger = require("morgan");
const app = express();
app.use(logger("dev"));
// …
注意: 中介軟體和路由函式按宣告順序呼叫。對於某些中介軟體,順序很重要(例如,如果會話中介軟體依賴於 cookie 中介軟體,那麼 cookie 處理程式必須首先新增)。幾乎總是將中介軟體放在設定路由之前呼叫,否則您的路由處理程式將無法訪問您的中介軟體新增的功能。
您可以編寫自己的中介軟體函式,並且您很可能需要這樣做(即使只是為了建立錯誤處理程式碼)。中介軟體函式和路由處理程式回撥之間的唯一區別是中介軟體函式具有第三個引數 next,中介軟體函式在沒有完成請求週期時(當呼叫中介軟體函式時,它包含必須呼叫的下一個函式)預計會呼叫它。
您可以使用 app.use() 將中介軟體函式新增到所有響應的處理鏈中,或者使用關聯的方法為特定 HTTP 動詞新增中介軟體函式:app.get()、app.post() 等。兩種情況下,路由的指定方式相同,儘管在呼叫 app.use() 時路由是可選的。
以下示例展示瞭如何使用兩種方法新增中介軟體函式,以及帶/不帶路由。
const express = require("express");
const app = express();
// An example middleware function
const a_middleware_function = function (req, res, next) {
// Perform some operations
next(); // Call next() so Express will call the next middleware function in the chain.
};
// Function added with use() for all routes and verbs
app.use(a_middleware_function);
// Function added with use() for a specific route
app.use("/someroute", a_middleware_function);
// A middleware function added for a specific HTTP verb and route
app.get("/", a_middleware_function);
app.listen(3000);
注意: 在上面,我們分別聲明瞭中介軟體函式,然後將其設定為回撥函式。在我們之前的路由處理函式中,我們在使用回撥函式時聲明瞭它。在 JavaScript 中,兩種方法都是有效的。
提供靜態檔案
您可以使用 express.static 中介軟體來提供靜態檔案,包括您的影像、CSS 和 JavaScript(static() 是唯一真正屬於Express 的中介軟體函式)。例如,您可以使用下面的程式碼行來提供影像、CSS 檔案和 JavaScript 檔案,這些檔案來自名為“public”的目錄,該目錄與您呼叫 node 的位置處於同一級別。
app.use(express.static("public"));
public 目錄中的任何檔案都可以透過將檔名(相對於基本“public”目錄)新增到基本 URL 來提供。例如
https://:3000/images/dog.jpg https://:3000/css/style.css https://:3000/js/app.js https://:3000/about.html
您可以多次呼叫 static() 來提供多個目錄。如果一箇中間件函式找不到檔案,它將被傳遞到下一個中介軟體(中介軟體呼叫的順序基於您的宣告順序)。
app.use(express.static("public"));
app.use(express.static("media"));
您還可以為靜態 URL 建立一個虛擬字首,而不是將檔案新增到基本 URL。例如,這裡我們 指定了一個掛載路徑,以便檔案在帶有字首“/media”的情況下載入。
app.use("/media", express.static("public"));
現在,您可以從 /media 路徑字首載入 public 目錄中的檔案。
https://:3000/media/images/dog.jpg https://:3000/media/video/cat.mp4 https://:3000/media/cry.mp3
注意: 另請參閱 在 Express 中提供靜態檔案。
處理錯誤
錯誤由一個或多個特殊的中介軟體函式處理,這些函式有四個引數,而不是通常的三個:(err, req, res, next)。例如
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(500).send("Something broke!");
});
這些函式可以返回任何所需的內容,但必須在所有其他 app.use() 和路由呼叫之後呼叫,以便它們是請求處理過程中的最後一箇中間件!
Express 帶有一個內建的錯誤處理程式,它處理應用程式中可能遇到的任何剩餘錯誤。這個預設的錯誤處理中介軟體函式是在中介軟體函式棧的末尾新增的。如果您將錯誤傳遞給 next() 並且您沒有在錯誤處理程式中處理它,它將由內建的錯誤處理程式處理;錯誤將與堆疊跟蹤一起寫入客戶端。
注意: 堆疊跟蹤不包含在生產環境中。要以生產模式執行它,您需要將環境變數 NODE_ENV 設定為“production”。
注意: HTTP404 和其他“錯誤”狀態程式碼不會被視為錯誤。如果您想要處理這些程式碼,您可以新增一箇中間件函式來執行此操作。有關更多資訊,請參閱 常見問題解答。
有關更多資訊,請參閱 錯誤處理(Express 文件)。
使用資料庫
Express 應用程式可以使用Node 支援的任何資料庫機制(Express 本身沒有定義任何關於資料庫管理的特定額外行為/要求)。有很多選項,包括 PostgreSQL、MySQL、Redis、SQLite、MongoDB 等。
為了使用這些選項,您必須首先使用 npm 安裝資料庫驅動。例如,要安裝流行的 NoSQL MongoDB 的驅動程式,您需要使用以下命令
npm install mongodb
資料庫本身可以安裝在本地或雲伺服器上。在您的 Express 程式碼中,您需要驅動程式,連線到資料庫,然後執行建立、讀取、更新和刪除 (CRUD) 操作。下面的示例(來自 Express 文件)展示瞭如何使用 MongoDB 查詢“哺乳動物”記錄。
這適用於 MongoDB 版本 ~ 2.2.33 的舊版本
const MongoClient = require("mongodb").MongoClient;
MongoClient.connect("mongodb://:27017/animals", (err, db) => {
if (err) throw err;
db.collection("mammals")
.find()
.toArray((err, result) => {
if (err) throw err;
console.log(result);
});
});
對於 MongoDB 版本 3.0 及更高版本
const MongoClient = require("mongodb").MongoClient;
MongoClient.connect("mongodb://:27017/animals", (err, client) => {
if (err) throw err;
const db = client.db("animals");
db.collection("mammals")
.find()
.toArray((err, result) => {
if (err) throw err;
console.log(result);
client.close();
});
});
另一種流行的方法是透過物件關係對映器 (“ORM”) 間接訪問您的資料庫。在這種方法中,您將資料定義為“物件”或“模型”,ORM 將這些資料對映到底層的資料庫格式。這種方法的優勢在於,作為開發人員,您可以繼續以 JavaScript 物件的形式思考,而不是資料庫語義,並且有一個明顯的位置可以執行對傳入資料的驗證和檢查。我們將在以後的文章中詳細討論資料庫。
有關更多資訊,請參閱 資料庫整合(Express 文件)。
渲染資料(檢視)
模板引擎(在Express 中也稱為“檢視引擎”)允許您在模板中指定輸出文件的結構,使用佔位符來表示生成頁面時將填充的資料。模板通常用於建立 HTML,但也可用於建立其他型別的文件。
Express 支援多種模板引擎,最著名的是 Pug(以前稱為“Jade”)、Mustache 和 EJS。每種引擎都有自己的優勢,可以用來解決特定的用例(可以透過網際網路搜尋輕鬆找到相對比較)。Express 應用程式生成器使用 Jade 作為預設引擎,但也支援其他幾種引擎。
在您的應用程式設定程式碼中,您設定要使用的模板引擎以及 Express 應該查詢模板的位置,使用“views”和“view engine”設定,如下所示(您還需要安裝包含您的模板庫的包!)。
const express = require("express");
const path = require("path");
const app = express();
// Set directory to contain the templates ('views')
app.set("views", path.join(__dirname, "views"));
// Set view engine to use, in this case 'some_template_engine_name'
app.set("view engine", "some_template_engine_name");
模板的外觀將取決於您使用的引擎。假設您有一個名為“index.<template_extension>”的模板檔案,該檔案包含名為“title”和“message”的資料變數的佔位符,您將在路由處理函式中呼叫 Response.render() 來建立和傳送 HTML 響應
app.get("/", function (req, res) {
res.render("index", { title: "About dogs", message: "Dogs rock!" });
});
有關更多資訊,請參閱 使用模板引擎與 Express(Express 文件)。
檔案結構
Express 對結構或您使用的元件沒有任何假設。路由、檢視、靜態檔案和其他特定於應用程式的邏輯可以存在於任意數量的檔案中,這些檔案具有任意目錄結構。雖然將整個Express 應用程式放在一個檔案中是完全可能的,但通常根據功能(例如,帳戶管理、部落格、論壇)和架構問題域(例如,模型、檢視或控制器,如果您恰好使用的是 MVC 架構)將應用程式拆分為檔案更有意義。
在以後的主題中,我們將使用Express 應用程式生成器,它會建立一個模組化的應用程式骨架,我們可以輕鬆地擴充套件它來建立 Web 應用程式。
總結
恭喜您,您已經完成了 Express/Node 之旅的第一步!您現在應該瞭解 Express 和 Node 的主要優勢,以及 Express 應用程式的主要部分大致是什麼樣子(路由、中介軟體、錯誤處理和模板程式碼)。您還應該瞭解,由於 Express 是一個無意見的框架,您將這些部分整合在一起的方式以及您使用的庫在很大程度上取決於您!
當然,Express 故意是一個非常輕量級的 Web 應用程式框架,因此它的許多優勢和潛力來自第三方庫和功能。我們將在接下來的文章中更詳細地討論這些內容。在下一篇文章中,我們將研究如何設定 Node 開發環境,以便您可以開始看到一些實際的 Express 程式碼。
另請參閱
- Venkat.R - 管理多個 Node 版本
- 模組(Node API 文件)
- Express(主頁)
- 基本路由(Express 文件)
- 路由指南(Express 文件)
- 使用模板引擎與 Express(Express 文件)
- 使用中介軟體(Express 文件)
- 編寫用於 Express 應用程式的中介軟體(Express 文件)
- 資料庫整合(Express 文件)
- 在 Express 中提供靜態檔案(Express 文件)
- 錯誤處理(Express 文件)