Node.jsWeb應用框架 — Express建立Server服務
小而靈活的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以外的文字,顯示的結果應該如下: