iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 19
1

承上篇 出處 , 有簡體版 , 進入後自行點選

寫在前面

MDN Node & Express 的綱目是: 介紹 、 安裝開發環境 、 教學 part1~7
照進度來看在結束鐵人賽只會寫到教學 part1 ,
結束後再一週產出一兩篇把它寫完就好

!! 我決定把 middleware 縮寫為 mw !!

Using middleware

Express app 會很常用到 mw , 包括處理一些 server 靜態檔案的問題 、 壓縮 HTTP res 。
Route function 以回傳 res to HTTP client 來結束 HTTP req-res cycle ; mw function 在處理 req 或 res 之後會呼叫放在 stacknext function , 這個 next 可能會是更多的 mw ( 或更多的 routes ) , mw 呼叫順序由開發者自行決定

Note : mw 可以換置 req & res obj 、 執行任何 code 、 還可以結束 req-res cycle , 如果 cycle 沒有被結束 , 它必須繼續呼叫 next() 傳遞控制訊息到下一個 mw function ( 否則 req 會被擺著沒人理 , 原文 be left hanging )

多數 app 會用第三方 mw , 為的是簡化常見的網站開發任務 , 例如 : cookies, sessions, authentucation, accessing req POST & JSON data, logging ... , 可以點這裡 list of middleware packages maintained by the Express team 查看提到的內容 。 其他 Express packages 可以用 NPM 取得

要用第三方 mw 前 , 我們要先用 NPM 安裝 。 例如:安裝 morgan HTTP req logger mw
morgan 究竟是啥? 參考連結: [Node.js打造API] 新增 middleware(body-parser、cors、morgan) 作者 (https://github.com/andy6804tw) , 這篇文章超白話易懂 , 大推 !

簡單來說會幫我們記下一些 req 狀態內容的工具 , status code 200, 404 ... 那些的
回到範例 :

$ npm install morgan

接著在 Express app obj 用 use() , 把 mw 新增到 stack 裡面

var express = require('express');
var logger = require('morgan');
var app = express();
app.use(logger('dev'));
...

Note: Mw & routing functions 需要注意呼叫的順序 , 有些 mw 順序影響很大 , 例: 如果 session mw 依存在 cookie mw 之下 , 那麼 cookie handler 就必須先加入。 通常設定 routes 之前 mw 會先被呼叫, 否則 route handlers 將無法存取我們新增的 mw ( 最後這句與簡中版有衝突, 待查證 )

我們可以寫屬於自己的 mw functions , 這也可能是必須的 ( 如果只有建造處理 error handling code (蛤?) ) 。 Mw function & route handler callback 兩者的唯一不同處是 mw 有第三個參數 next , 這個 next 是 mw 先預備起來, 如果未完成 req cycle 就拿來呼叫用的

app.use()app.add()(註) 新增 mw function 到作業鏈中 , 而要選用何者? 這取決於是否要將 mw 應用在所有 res 還是特定 HTTP 行為的 res 就好 ; 兩者都可以設定同個路由, 雖然在呼叫 app.use() 時路由設定是非必要的

下方範例演示如何用兩種方式新增 mw function , 同時也有路由設定與未設定:

var express = require('express');
var app = express();

// middleware function 範例
var a_middleware_function = function(req, res, next) {
  // ... 其他程式碼
  next(); // 呼叫 next() , Express 會呼叫在這個作業鏈中的 next middleware function.
}

// 用 use() 新增 , 所有 routes and verbs 的情況
app.use(a_middleware_function);

// 用 use() 新增 , 指定 route 的情況
app.use('/someroute', a_middleware_function);

// 新增一個 middleware function , 指定 HTTP verb and route 的情況
app.get('/', a_middleware_function);

app.listen(3000);

註: 我認為上面的 app.add() 可能是 .add() 意指要用 .get()/.post() ... 來代換 , 因 MDN 本身舉例的 code 裡面沒有 .add() , 官網搜尋及列表裡也沒看到 .add() method (http://expressjs.com/zh-tw/api.html) ; 有確定之後再回頭來改

JS Tips: 上例我們單獨宣告 mw function, 然後把它設為 callback。 在先前的 route handler function 中, 它被使用時我們也把它宣告為 callback 。 在 JS 中兩個都可以

Express 官方文件有更多說明, 請點選 using & writing Express mw ( 這兩個連結都是官方中文版喔!! )

Serving static files

express.static mw 處理靜態檔案, 包括 img, CSS, JS ( .static() 是 Express 的原生 mw ) 。 以下範例是在 serve 跟呼叫 node 同目錄下 public 資料夾裡的靜態檔 ( img, CSS, JS ... )

app.use(express.static('public));

完整寫法

const express = require('express')
const app = express()

app.listen(3000, function() {
  console.log('Example app listening on port 3000!');
});

app.use(express.static('public));

當前資料夾結構 ( 如果沒顯示點這裡 )

所有 public 資料夾的檔案都被 serve 過 , 可以用 URL 來開它們了 , 如:

http://localhost:3000/images/logo.jpg

也可以 serve 多個資料夾目錄 , 如果 mw function 找不到某個文件 , 它會傳給後續的 mw , 會受到 mw 書寫順序的影響

app.use(express.static('public'));
app.use(express.static('media'));

可以為靜態 URL 增加前綴 , 讓這些檔案可以被前綴乘載 。 例如:

app.use('/media', express.static('public'));
http://localhost:3000/media/images/logo.jpg

Serving static files in Express 有更詳細的資訊


上一篇
18日: Express/Node introduction ( 非同步 APIs 、 建立 route handlers 、 使用 middleware )
下一篇
20日: Express/Node introduction ( ERR 處理 、 使用 db 、 把資料渲染到畫面 、 檔案結構 、 總結 )
系列文
還在想要買哪一堂線上課程嗎?培養看文件的習慣吧!用 MDN 文件學後端:NodeJS & MongooseDB30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言