Express 教程第 2 部分:建立網站框架
我們《Express 教程》中的這篇第二篇文章展示瞭如何建立一個“骨架”網站專案,然後您可以繼續用特定於站點的路由、模板/檢視和資料庫呼叫填充它。
| 先決條件 | 設定 Node 開發環境。回顧 Express 教程。 |
|---|---|
| 目標 | 能夠使用Express 應用程式生成器啟動您自己的新網站專案。 |
概述
本文介紹瞭如何使用Express 應用程式生成器工具建立“骨架”網站,然後您可以用特定於站點的路由、檢視/模板和資料庫呼叫填充它。在本例中,我們將使用該工具為我們的本地圖書館網站建立框架,稍後我們將向其中新增站點所需的所有其他程式碼。此過程非常簡單,只需在命令列上使用新的專案名稱呼叫生成器即可,還可以選擇指定站點的模板引擎和 CSS 生成器。
以下部分將向您展示如何呼叫應用程式生成器,並提供一些關於不同檢視/CSS 選項的說明。我們還將解釋骨架網站的結構。最後,我們將展示如何執行網站以驗證其是否正常工作。
注意
- Express 應用程式生成器並不是 Express 應用程式的唯一生成器,生成的專案也不是構建檔案和目錄的唯一可行方法。但是,生成的站點確實具有易於擴充套件和理解的模組化結構。有關最小Express 應用程式的資訊,請參閱Hello world 示例(Express 文件)。
- Express 應用程式生成器使用
var宣告大多數變數。在本教程中,我們已將其中大多數更改為const(以及一些更改為let),因為我們希望演示現代 JavaScript 實踐。 - 本教程使用Express 應用程式生成器建立的package.json中定義的Express和其他依賴項的版本。這些不是(必然是)最新版本,您可能希望在將真實應用程式部署到生產環境時更新它們。
使用應用程式生成器
您應該已在設定 Node 開發環境的過程中安裝了生成器。作為快速提醒,您可以使用 npm 包管理器全域性安裝生成器工具,如下所示
npm install express-generator -g
生成器有許多選項,您可以在命令列上使用--help(或-h)命令檢視這些選項
> express --help
Usage: express [options] [dir]
Options:
--version output the version number
-e, --ejs add ejs engine support
--pug add pug engine support
--hbs add handlebars engine support
-H, --hogan add hogan.js engine support
-v, --view <engine> add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
--no-view use static html instead of view engine
-c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain CSS)
--git add .gitignore
-f, --force force on non-empty directory
-h, --help output usage information
您可以指定 express 在當前目錄中建立專案,使用Jade檢視引擎和普通 CSS(如果您指定目錄名稱,則專案將在具有該名稱的子資料夾中建立)。
express
您還可以使用--view選擇檢視(模板)引擎和/或使用--css選擇 CSS 生成引擎。
注意:選擇模板引擎的其他選項(例如--hogan、--ejs、--hbs等)已棄用。使用--view(或-v)。
我應該使用哪個檢視引擎?
Express 應用程式生成器允許您配置許多流行的檢視/模板引擎,包括EJS、Hbs、Pug(Jade)、Twig和Vash,儘管如果您沒有指定檢視選項,它預設選擇 Jade。Express 本身還可以支援大量其他模板語言開箱即用。
注意:如果您想使用生成器不支援的模板引擎,請參閱在 Express 中使用模板引擎(Express 文件)以及目標檢視引擎的文件。
一般來說,您應該選擇一個能夠提供您所需所有功能並讓您更快地提高生產力的模板引擎——或者換句話說,就像您選擇任何其他元件一樣!比較模板引擎時需要考慮的一些事項
- 生產力時間——如果您的團隊已經具備某種模板語言的經驗,那麼他們很可能使用該語言更快地提高生產力。如果不是,那麼您應該考慮候選模板引擎的相對學習曲線。
- 流行度和活躍度——檢視引擎的流行度以及它是否擁有活躍的社群。在網站的整個生命週期中,當出現問題時能夠獲得支援非常重要。
- 樣式——一些模板引擎使用特定的標記來指示“普通”HTML 中插入的內容,而其他模板引擎則使用不同的語法構建 HTML(例如,使用縮排和塊名稱)。
- 效能/渲染時間。
- 功能——您應該考慮您檢視的引擎是否具有以下功能
- 佈局繼承:允許您定義基本模板,然後僅“繼承”您希望在特定頁面中有所不同的部分。這通常比透過包含許多必需的元件或每次從頭開始構建模板來構建模板更好的方法。
- “包含”支援:允許您透過包含其他模板來構建模板。
- 簡潔的變數和迴圈控制語法。
- 能夠在模板級別過濾變數值,例如將變數大寫或格式化日期值。
- 能夠生成除 HTML 之外的輸出格式,例如 JSON 或 XML。
- 支援非同步操作和流。
- 客戶端功能。如果模板引擎可以在客戶端上使用,則可以將所有或大部分渲染工作在客戶端完成。
注意:網際網路上有許多資源可以幫助您比較不同的選項!
對於這個專案,我們將使用Pug模板引擎(這是最近更名的 Jade 引擎),因為它是最流行的 Express/JavaScript 模板語言之一,並且由生成器開箱即用地支援。
我應該使用哪個 CSS 樣式表引擎?
我應該使用哪個資料庫?
生成的程式碼不使用/包含任何資料庫。Express 應用程式可以使用Node支援的任何資料庫機制(Express本身沒有為資料庫管理定義任何特定的額外行為/要求)。
我們將在後面的文章中討論如何與資料庫整合。
建立專案
對於我們將要構建的示例本地圖書館應用程式,我們將使用Pug模板庫和無 CSS 引擎建立一個名為express-locallibrary-tutorial的專案。
首先,導航到您想要建立專案的目錄,然後在命令提示符中執行Express 應用程式生成器,如下所示
express express-locallibrary-tutorial --view=pug
生成器將建立(並列出)專案的檔案。
create : express-locallibrary-tutorial\
create : express-locallibrary-tutorial\public\
create : express-locallibrary-tutorial\public\javascripts\
create : express-locallibrary-tutorial\public\images\
create : express-locallibrary-tutorial\public\stylesheets\
create : express-locallibrary-tutorial\public\stylesheets\style.css
create : express-locallibrary-tutorial\routes\
create : express-locallibrary-tutorial\routes\index.js
create : express-locallibrary-tutorial\routes\users.js
create : express-locallibrary-tutorial\views\
create : express-locallibrary-tutorial\views\error.pug
create : express-locallibrary-tutorial\views\index.pug
create : express-locallibrary-tutorial\views\layout.pug
create : express-locallibrary-tutorial\app.js
create : express-locallibrary-tutorial\package.json
create : express-locallibrary-tutorial\bin\
create : express-locallibrary-tutorial\bin\www
change directory:
> cd express-locallibrary-tutorial
install dependencies:
> npm install
run the app (Bash (Linux or macOS))
> DEBUG=express-locallibrary-tutorial:* npm start
run the app (PowerShell (Windows))
> $ENV:DEBUG = "express-locallibrary-tutorial:*"; npm start
run the app (Command Prompt (Windows)):
> SET DEBUG=express-locallibrary-tutorial:* & npm start
在輸出的末尾,生成器提供了有關如何安裝依賴項(如package.json檔案中列出的)以及如何在不同作業系統上執行應用程式的說明。
注意:生成器建立的檔案將所有變數定義為var。在繼續之前,開啟所有生成的檔案並將var宣告更改為const(本教程的其餘部分假設您已這樣做)。
執行網站框架
此時,我們有一個完整的骨架專案。該網站實際上還沒有做太多事情,但值得執行它以表明它可以正常工作。
- 首先,安裝依賴項(
install命令將獲取專案package.json檔案中列出的所有依賴項包)。bashcd express-locallibrary-tutorial npm install - 然後執行應用程式。
- 在 Windows CMD 提示符下,使用以下命令batch
SET DEBUG=express-locallibrary-tutorial:* & npm start - 在 Windows Powershell 中,使用以下命令powershell
ENV:DEBUG = "express-locallibrary-tutorial:*"; npm start注意:本教程中未介紹 Powershell 命令(提供的“Windows”命令假設您正在使用 Windows CMD 提示符)。
- 在 macOS 或 Linux 上,使用以下命令bash
DEBUG=express-locallibrary-tutorial:* npm start
- 在 Windows CMD 提示符下,使用以下命令
- 然後在瀏覽器中載入
https://:3000/以訪問應用程式。
您應該會看到一個如下所示的瀏覽器頁面
恭喜!您現在擁有一個可以透過埠 3000 訪問的工作 Express 應用程式。
注意:您也可以只使用npm start命令啟動應用程式。如上所示指定 DEBUG 變數可啟用控制檯日誌記錄/除錯。例如,當您訪問上述頁面時,您將看到如下所示的除錯輸出
SET DEBUG=express-locallibrary-tutorial:* & npm start
> express-locallibrary-tutorial@0.0.0 start D:\github\mdn\test\exprgen\express-locallibrary-tutorial > node ./bin/www express-locallibrary-tutorial:server Listening on port 3000 +0ms GET / 304 490.296 ms - - GET /stylesheets/style.css 200 4.886 ms - 111
啟用檔案更改時伺服器重啟
您對 Express 網站所做的任何更改目前在您重新啟動伺服器之前都不可見。每次進行更改時都必須停止和重新啟動伺服器很快就會變得非常令人惱火,因此值得花時間在需要時自動重新啟動伺服器。
一個方便的工具是nodemon。它通常是全域性安裝的(因為它是一個“工具”),但在這裡我們將將其作為開發依賴項在本地安裝和使用,以便任何使用該專案的開發人員在安裝應用程式時自動獲取它。在骨架專案的根目錄中使用以下命令
npm install --save-dev nodemon
如果您仍然選擇將nodemon全域性安裝到您的機器上,而不僅僅是安裝到專案的package.json檔案中
npm install -g nodemon
如果您開啟專案的package.json檔案,您現在將看到一個包含此依賴項的新部分
"devDependencies": {
"nodemon": "^3.1.3"
}
由於該工具不是全域性安裝的,因此我們無法從命令列啟動它(除非我們將其新增到路徑中),但我們可以從 npm 指令碼中呼叫它,因為 npm 瞭解所有已安裝的包。找到您的 package.json 的scripts部分。最初,它將包含一行,以"start"開頭。透過在該行的末尾加上逗號並新增"devstart"和"serverstart"行來更新它
- 在 Linux 和 macOS 上,scripts 部分將如下所示json
"scripts": { "start": "node ./bin/www", "devstart": "nodemon ./bin/www", "serverstart": "DEBUG=express-locallibrary-tutorial:* npm run devstart" }, - 在 Windows 上,“serverstart”值將如下所示(如果使用命令提示符)bash
"serverstart": "SET DEBUG=express-locallibrary-tutorial:* & npm run devstart"
我們現在可以幾乎與以前完全相同的方式啟動伺服器,但使用devstart命令。
注意:現在,如果您編輯專案中的任何檔案,伺服器將重新啟動(或者您可以在任何時候在命令提示符下鍵入rs來重新啟動它)。您仍然需要重新載入瀏覽器以重新整理頁面。
我們現在必須呼叫“npm run <scriptname>”而不是僅僅npm start,因為“start”實際上是一個 npm 命令,它對映到命名指令碼。我們本可以替換start指令碼中的命令,但我們只想在開發期間使用nodemon,因此建立新的指令碼命令更有意義。
上面在package.json中的指令碼中新增的serverstart命令就是一個很好的例子。使用這種方法意味著您不再需要鍵入很長的命令來啟動伺服器。請注意,新增到指令碼中的特定命令僅適用於 macOS 或 Linux。
生成的專案
現在讓我們看看我們剛剛建立的專案。
目錄結構
生成的專案,現在您已經安裝了依賴項,具有以下檔案結構(檔案是不以“/”為字首的專案)。package.json檔案定義了應用程式依賴項和其他資訊。它還定義了一個啟動指令碼,該指令碼將呼叫應用程式入口點,即 JavaScript 檔案/bin/www。這設定了一些應用程式錯誤處理,然後載入app.js來完成其餘工作。應用程式路由儲存在routes/目錄下的單獨模組中。模板儲存在/views目錄下。
express-locallibrary-tutorial
app.js
/bin
www
package.json
package-lock.json
/node_modules
[about 6700 subdirectories and files]
/public
/images
/javascripts
/stylesheets
style.css
/routes
index.js
users.js
/views
error.pug
index.pug
layout.pug
以下部分將更詳細地描述這些檔案。
package.json
package.json檔案定義了應用程式依賴項和其他資訊
{
"name": "express-locallibrary-tutorial",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
"pug": "2.0.0-beta11"
},
"devDependencies": {
"nodemon": "^3.1.3"
}
}
scripts 部分首先定義了一個“start”指令碼,當我們呼叫npm start啟動伺服器時,我們正在呼叫它(此指令碼由Express Application Generator新增)。從指令碼定義中,您可以看到這實際上是用node啟動了JavaScript檔案./bin/www。
我們已經在啟用檔案更改時伺服器重啟中修改了此部分,添加了devstart和serverstart指令碼。這些可用於用nodemon而不是node啟動相同的./bin/www檔案(此版本的指令碼適用於 Linux 和 macOS,如上所述)。
"scripts": {
"start": "node ./bin/www",
"devstart": "nodemon ./bin/www",
"serverstart": "DEBUG=express-locallibrary-tutorial:* npm run devstart"
},
依賴項包括express包和我們選擇的檢視引擎的包(pug)。此外,我們還有以下在許多 Web 應用程式中很有用的包
- cookie-parser:用於解析 cookie 標頭並填充
req.cookies(基本上提供了一種訪問 cookie 資訊的便捷方法)。 - debug:一個微型的 node 除錯實用程式,其模型來自 node 核心除錯技術。
- morgan:一個用於 node 的 HTTP 請求記錄器中介軟體。
- http-errors:根據需要建立 HTTP 錯誤(用於 express 錯誤處理)。
生成專案中的預設版本有點過時了。將您的package.json檔案的依賴項部分替換為以下文字,該文字指定了撰寫本文時這些庫的最新版本
"dependencies": {
"cookie-parser": "^1.4.6",
"debug": "^4.3.5",
"express": "^4.19.2",
"http-errors": "~2.0.0",
"morgan": "^1.10.0",
"pug": "3.0.3"
},
然後使用以下命令更新已安裝的依賴項
npm install
注意:定期更新到依賴庫的最新相容版本是一個好主意——這甚至可以作為持續整合設定的一部分自動或半自動地完成。
通常,庫對次要版本和補丁版本的更新保持相容。我們在上面每個版本前都添加了^,以便我們可以透過執行以下命令自動更新到最新的minor.patch版本
npm update --save
主要版本會更改相容性。對於這些更新,我們需要手動更新package.json和使用該庫的程式碼,並對專案進行廣泛的重新測試。
www 檔案
檔案/bin/www是應用程式的入口點!首先,它會require()“真實”的應用程式入口點(app.js,位於專案根目錄),該入口點設定並返回express()應用程式物件。require()是CommonJS 方法,用於將 JavaScript 程式碼、JSON 和其他檔案匯入到當前檔案中。在這裡,我們使用相對路徑指定app.js模組,並省略可選的(.js)副檔名。
#!/usr/bin/env node
/**
* Module dependencies.
*/
const app = require("../app");
注意:Node.js 14 及更高版本支援用於匯入 JavaScript(ECMAScript)模組的 ES6 import 語句。要使用此功能,您必須將"type": "module",新增到您的 Express package.json檔案中,應用程式中的所有模組都必須使用import而不是require(),並且對於相對匯入,您必須包含副檔名(有關更多資訊,請參閱Node 文件)。雖然使用import有很多好處,但本教程使用require()是為了與Express 文件相匹配。
此檔案中的其餘程式碼使用app設定為特定埠(在環境變數中定義,如果變數未定義則為 3000)設定節點 HTTP 伺服器,並開始偵聽和報告伺服器錯誤和連線。目前,您實際上不需要了解有關程式碼的任何其他資訊(此檔案中的所有內容都是“樣板程式碼”),但如果您有興趣,可以隨意檢視它。
app.js
此檔案建立一個express應用程式物件(根據慣例命名為app),使用各種設定和中介軟體設定應用程式,然後從模組匯出應用程式。下面的程式碼僅顯示建立和匯出應用程式物件的檔案部分
const express = require("express");
const app = express();
// …
module.exports = app;
回到上面的www入口點檔案中,當匯入此檔案時,正是此module.exports物件被提供給呼叫方。
讓我們詳細介紹一下app.js檔案。首先,我們使用require()將一些有用的 node 庫匯入到檔案中,包括我們之前使用 npm 為應用程式下載的http-errors、express、morgan和cookie-parser;以及path,它是一個用於解析檔案和目錄路徑的核心 Node 庫。
const createError = require("http-errors");
const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const logger = require("morgan");
然後,我們從我們的路由目錄require()模組。這些模組/檔案包含用於處理特定相關“路由”(URL 路徑集)的程式碼。例如,當我們擴充套件骨架應用程式以列出庫中的所有書籍時,我們將新增一個新檔案來處理與書籍相關的路由。
const indexRouter = require("./routes/index");
const usersRouter = require("./routes/users");
注意:此時,我們只是匯入了模組;我們還沒有實際使用它的路由(這發生在稍後一點的檔案中)。
接下來,我們使用匯入的express模組建立app物件,然後使用它來設定檢視(模板)引擎。設定引擎有兩個部分。首先,我們將'views'值設定為指定儲存模板的資料夾(在本例中為子資料夾/views)。然後,我們將'view engine'值設定為指定模板庫(在本例中為“pug”)。
const app = express();
// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");
下一組函式呼叫app.use()將我們上面匯入的中介軟體庫新增到請求處理鏈中。例如,express.json()和express.urlencoded()需要填充req.body表單欄位。在這些庫之後,我們還使用express.static中介軟體,它使Express服務專案根目錄中/public目錄中的所有靜態檔案。
app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));
現在所有其他中介軟體都已設定,我們將(之前匯入的)路由處理程式碼新增到請求處理鏈中。匯入的程式碼將為網站的不同部分定義特定的路由
app.use("/", indexRouter);
app.use("/users", usersRouter);
注意:上面指定的路徑('/'和'/users')被視為匯入檔案中定義的路由的字首。例如,如果匯入的users模組為/profile定義了一個路由,則您可以在/users/profile訪問該路由。我們將在後面的文章中更多地討論路由。
檔案中的最後一箇中間件添加了錯誤和 HTTP 404 響應的處理程式方法。
// catch 404 and forward to error handler
app.use((req, res, next) => {
next(createError(404));
});
// error handler
app.use((err, req, res, next) => {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get("env") === "development" ? err : {};
// render the error page
res.status(err.status || 500);
res.render("error");
});
Express 應用程式物件(app)現已完全配置。最後一步是將其新增到模組匯出中(這允許它被/bin/www匯入)。
module.exports = app;
路由
路由檔案/routes/users.js如下所示(路由檔案具有類似的結構,因此我們不需要也顯示index.js)。首先,它載入express模組並使用它來獲取express.Router物件。然後它在該物件上指定一個路由,最後從模組匯出路由器(這允許將檔案匯入到app.js中)。
const express = require("express");
const router = express.Router();
/* GET users listing. */
router.get("/", (req, res, next) => {
res.send("respond with a resource");
});
module.exports = router;
該路由定義了一個回撥函式,每當檢測到具有正確模式的 HTTP GET 請求時,都會呼叫該函式。匹配模式是在匯入模組時指定的路由('/users')加上在此檔案中定義的任何內容('/')。換句話說,當接收到/users/的 URL 時,將使用此路由。
注意:透過使用 node 執行伺服器並在瀏覽器中訪問 URL 來試用它:https://:3000/users/。您應該看到一條訊息:“respond with a resource”。
上面需要注意的一件事是回撥函式具有第三個引數'next',因此它是一箇中間件函式,而不是簡單的路由回撥。雖然程式碼目前沒有使用next引數,但如果將來您想向'/'路由路徑新增多個路由處理程式,它可能會很有用。
檢視(模板)
檢視(模板)儲存在/views目錄中(如app.js中指定),並使用副檔名.pug。方法Response.render()用於呈現指定的模板以及物件中傳遞的命名變數的值,然後將結果作為響應傳送。在下面來自/routes/index.js的程式碼中,您可以看到該路由如何使用模板“index”傳遞模板變數“title”來呈現響應。
/* GET home page. */
router.get("/", (req, res, next) => {
res.render("index", { title: "Express" });
});
上面路由的對應模板如下所示(index.pug)。我們稍後會詳細討論語法。您現在只需要知道變數title(值為'Express')插入到模板中指定的位置。
extends layout
block content
h1= title
p Welcome to #{title}
挑戰自己
在/routes/users.js中建立一個新的路由,它將在 URL /users/cool/顯示文字“You're so cool”。透過執行伺服器並在瀏覽器中訪問https://:3000/users/cool/來測試它
總結
您現在已經為本地圖書館建立了一個骨架網站專案,並驗證了它可以使用node執行。最重要的是,您也瞭解了專案的結構,因此您對需要在哪裡進行更改以新增本地圖書館的路由和檢視有一個很好的瞭解。
接下來,我們將開始修改骨架,使其作為圖書館網站工作。
另請參閱
- Express 應用程式生成器(Express 文件)
- 使用 Express 的模板引擎(Express 文件)