Node.jsWeb應用框架 — Express建立Server服務

Sean Yeh
Web Design Zone
Published in
10 min readFeb 12, 2020
Photo by Takehiro Tomiyama on Unsplash

小而靈活的Express

上一篇我們使用Node.js中的原生模組:http 建立了一個最簡單的server。這一篇我們要使用Express.js來協助我們寫js server。什麼是Express?

Express 是 Node.js Web App架構,據說建構者TJ Holowaychukr是受到一種Ruby框架(Sinatra)的啟發而建構成的,讓開發者可以更快速,更有效的開發並且維護網站。目前Express在MIT許可證下作為開放原始碼軟體發行。

Express框架具有下面幾個特性:

它小巧,不臃腫,提供最少的階層。可以節省工作時間;

它靈活,具有可擴充性,可以依照個別需要加入各種套件;

它是Web App框架;

它是單頁式SPA應用程式;

它是多網頁與SPA混合式Web應用程式。

Express:

  • 可以用來呼應HTTP的請求。
  • 定義了路由表,可用於執行不同的HTTP請求。
  • 可以透過Template模板傳遞參數來動態產生HTML頁面。

Express被設計做為 Web 與行動應用程式提供一組健全的架構。

Express環境設定

在使用Express前,需要先進行環境的設定。首先要建立package.json檔案。請在終端機 command line輸入下列指令。

$ npm init

以上指令執行完畢後,將在專案中產生一個package.json檔案。內容會因個人的設定而異,不過大至上如下:

{
"name": "npm_express",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
}

這是package.json檔案最陽春的設定。

安裝 express

緊接著我們要使用NPM來安裝express.js。請輸入下列指令。

$ npm install express --save

安裝後,可以看看package.json檔案裡面是不是出現下面幾行粗體的部分?因為輸入了 — save的關係,在dependencies的地方會出現express與其版本號碼。

{
"name": "npm_express",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
}
}

如果出現了,就表示express已經安裝完畢。

透過Express建立伺服器

環境設定完畢之後,我們要開始進入正題,使用Express.js來協助我們寫js server。

載入express模組

我們開啟全新的檔案(例如:myServer.js),在這個空白檔案中,先載入express,載入方法如下:

let express = require("express")
//載入express模組

在這裏載入的express,就像是上一篇我們載入http模組一樣。與http模組不同的是,express模組不是Node.js原生的模組。必須先透過npm安裝之後,才可以使用。

let http = require("http")
//載入http模組

建立使用express

建立使用express(),並且將它指定給變數ourApp

let ourApp = express()
// 使用express

監聽port

監聽 port 3000,使用其他port也可以:

ourApp.listen(3000)
//監聽PORT

get()處理收發訊息

app.get()是添加路由的方法,其中以app.get()與app.post最為常見。使用 get() 收到路由訊息後,會告訴server當收到時該如何處理。

ourApp.get(a, b)

get()裡面要放兩個參數,我們姑且成為a與b。

其中,第一個參數a是想要放想傳遞的網址,我們先加入首頁 (‘ / ’) 。

第二個參數b是一個匿名函數 function () { }。這個函數要定義當瀏覽者瀏覽參數a指定的頁面首頁)時,應該要回覆瀏覽者的訊息。我們使用Express的擴充:res.send()回覆瀏覽者訊息(而不是使用Node 的 res.end)。

function (req, res) {    res.send("Welcome");}

比較我們之前使用Node原生http模組寫的Server,一樣使用匿名函數,一樣有兩個參數req, res。差別在之前使用res.end()在這裡我們改用res.send()。

function (req, res) {   //使用Node原生http
res.end("welcome")
}

啟動server

$ node myServer.js

啟動伺服器後,如果正常顯示出Welcome,就表示已經完成server的服務了。程式碼是不是比之前的簡潔?

接著我們來看GET與POST有什麼不同?

GET與POST的差異

我們先修改一下上面send()部分的內容:

function (req, res) {res.send(`<form action="/answer" method="POST">
<p>晴天的天空是什麼顏色?</p>
<input name="skyColor" autocomplete="off">
<button>送出答案</button>
</form>
`)
}

輸出結果:上面有一個input輸入框。輸入框的地方顯示POST。

如果我們從輸入框輸入資料,就是走POST的方式。

接著,我們再加上下面兩段程式碼:

第一段:用POST

ourApp.post('/answer', function (req, res) {res.send("謝謝您撥空填寫表單")})

第二段:用GET

ourApp.get('/answer', function (req, res) {res.send("迷路了嗎? 這裡什麼都沒有")})

外加下面這段middleware,express.urlencoded()為了讓post可以被解讀。

ourApp.use(express.urlencoded({  extended: false}))

以下是所有程式碼:


let express = require("express")
let ourApp = express()ourApp.use(express.urlencoded({extended: false}))ourApp.get('/', function (req, res) { res.send(` <form action="/answer" method="POST"> <p>晴天的天空是什麼顏色?</p> <input name="skyColor" autocomplete="off"> <button>送出答案</button> </form> `) })ourApp.post('/answer', function (req, res) { res.send("謝謝您撥空填寫表單")})ourApp.get('/answer', function (req, res) { res.send("迷路了嗎? 這裡什麼都沒有")})ourApp.listen(3000)

我們藉由以上的程式碼說明GET與POST的差異。當我們在頁面上按下submit(送出答案)按鈕時。頁面會到達http://localhost:3000/answer頁,並回覆『謝謝您撥空填寫表單』。可以看出來,目前程式執行的是第一段程式碼。可見這時候走的是POST方式。

ourApp.post('/answer', function (req, res) {    res.send("謝謝您撥空填寫表單")})

如果,我們直接在網址列輸入 http://hocalhost:3000/answer的話,雖然網址一樣,頁面則會顯示『迷路了嗎? 這裡什麼都沒有』。可見這時候走的是第二段GET程式碼。

ourApp.get('/answer', function (req, res) {    res.send("迷路了嗎? 這裡什麼都沒有")})

因此,如果要取得網址上面的參數,應該使用的是GET方式。

判斷使用者的輸入:POST

接著我們要判斷使用者輸入的內容,依照不同的內容做出不一樣的反應。於是我們可以利用if判斷式來進行條件判斷。在這裡我們希望使用者輸入不同的顏色,並且給予不同的反應。判斷式如下:

ourApp.post('/answer', function (req, res) {    if (x == "blue") {        // do something...    } else {        // do other things..    }})

其中,x == “blue”中的 x 是什麼?x是我們從網頁表單上面透過input欄位蒐集到的內容。

由於我們已經在 input欄位中<input name=”skyColor” autocomplete=”off”>,指定name為skyColor,我們可以透過它來勾住這個輸入框。我們把x替換為req.body.skyColor

ourApp.post('/answer', function (req, res) {    if (req.body.skyColor == "blue") {        // do something...    } else {        // do other things..    }})

注意:為了避免使用者輸入大小寫不同產生不一樣的結果,我們可以強制將它轉換為大寫(或小寫):

req.body.skyColor.toUpperCase() == "BLUE"

這樣子,不論使用者輸入大寫或小寫的blue,都會產生同樣的結果。

接下來填入server針對各個條件應該反應的行為。我們這裡使用templete string(``)將html原始碼加入各個位置:

ourApp.post('/answer', function (req, res) {
if (req.body.skyColor == "blue") { res.send(` <p>恭喜您,答對了。這是正確答案</p>
<a href="/">回首頁</a>
`) } else { res.send(` <p>真可惜,答錯了。</p>
<a href="/">回首頁</a>
`) }})

啟動server

$ node myServer.js

啟動伺服器後,如果顯示正常,就表示已經啟動server的服務了。接下來就可以試試輸入字串。先輸入blue,不論是blue還是Blue、BLUE或其他大小寫的組合,答案應該如下:

接著,試試blue以外的文字,顯示的結果應該如下:

--

--

Sean Yeh
Web Design Zone

# Taipei, Internet Digital Advertising,透過寫作讓我們回想過去、理解現在並思考未來。並樂於分享,這才是最大贏家。