Express 筆記:簡單使用介紹
Node.js
Node.js 是一個能讓 JavaScript 執行在瀏覽器外的執行環境,以往我們需要學會多個程式語言:例如Python或PHP來讓網頁連接到後端服務。藉由Node.js的出現,開發者能夠統一開發網頁前後端的程式語言,直接以熟悉的JavaScript處理一系列的後端應用。
在Node.js上建立一個簡單的Web server:
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
這會創造一個Web Server並監聽 http://127.0.0.1:300/ 上的HTTP請求,收到請求時回傳「Hello World」的純文字回應。
Express
但Node原生並不能夠爲不同的HTTP Methods(常見的:GET、POST等等)作出特定的處理,或動態地產生Response,這造就了本篇要介紹的重點Node.js Web應用程式框架Express的誕生。
以下以Express建立一個同樣的Web server:
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
app.get() 方法指定了當收到HTTP GET請求時會執行callback function,並簡單地呼叫send()對回應回傳「Hello World」字串。
除了字串,send() 亦能夠回傳合法的HTML block:
app.get('/', (req, res) => {
res.send('<h1>Hello World!</h1>');
});
如果web server是爲了製作出API,我們可能會想要把一些Object送到Client side,同樣可以利用send()回傳:
app.get('/', (req, res) => {
let Object = {
name: "Edison",
occupation: "front-end engineer"
};
res.send(Object);
});
在瀏覽器打開會是一個JSON格式的物件。
當我們需要回傳一整個HTML file的時候,透過sendFile()可以回傳需要的檔案:
app.get('/', (req, res) => {
//注意不能直接回傳檔案名,需要絕對路徑!
res.sendFile(__dirname + "/index.html");
});
Routing 路由路徑
透過多個方法可以處理不同的requests:
//app.post()可以處理post request,亦有put、head、delete、options..等
app.get("/", (req, res) => {
res.send("This is the homepage.");
});
app.get("/product1", (req, res) => {
res.send("This is a page for product1.");
});
app.get("/about", (req, res) => {
res.send("This is an about page.");
});
//處理不符合以上條件的get requests,* 代表所有pattern
app.get("*", (req, res) => {
res.send("Cannot find page.");
});
處理一定pattern的requests:
app.get("/fruits/:somefruit", (req, res) => {
//req.params能回傳requests的參數物件
res.send(`You are looking for ${req.params.somefruit}`);
});
也可以透過object destructuring賦值到獨立變數:
app.get("/fruits/:somefruit", (req, res) => {
let { somefruit } = req.params
res.send(`You are looking for ${somefruit}`);
});
Routing for query
先在 index.html 中建立一個 form,再處理 root( / )的 get requests:
<body>
<form action="/formHandling" method="POST">
<label for="fullname">Your name:</label>
<input type="text" id="fullname" name="fullname" />
<label for="age">Your age:</label>
<input type="number" id="age" name="age" />
<button type="submit">Submit</button>
</form>
</body>
const path = require("path");
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "index.html"));
});
當使用者按下 Submit 的時候就會馬上把 form 裏面的資料丟進 /formHandling,這個時候我們需要在server裏面處理 /formHandling 的 post request:
//我們可以透過express的middleware解讀body
app.use(express.urlencoded({extened: true}));
//處理"/formHandling"的post request
app.post("/formHandling", (req, res) => {
let { fullname, age } = req.body;
res.send(`Thank you for posting. Your name is ${fullname} and aging ${age}.`);
});
假設你現在要處理的 from 屬於 get method,我們 server 便不再需要 middleware 並可以改寫成:
app.get("/formHandling", (req, res) => {
let { fullname, age } = req.query;
res.send(`Thank you for posting. Your name is ${fullname} and aging ${age}.`);
})
導入靜態文件
靜態文件例如 Stylesheet檔案以及影像檔等在 Node.js 的環境下需要作特別的設定,將含有靜態檔案的目錄名稱傳遞給 express.static middleware,就能直接開始提供檔案:
app.use(express.static("public"));
並於根目錄建立 public 目錄:
這時候 index.html 的 link 就能正確指向 public 目錄內的檔案:
<link rel="stylesheet" href="./styles/style.css" />
Styling 亦會正確套入。
處理404 Not found
大家有上過網應該就會知道 404 not found 這個錯誤訊息,404 error 指的是沒有找到關於這個頁面的任何內容,因爲這個錯誤會因爲種種問題產生,所以很多網站會爲網站設計 404 error 頁面,導向使用者到其他有效頁面。
其中當然要先建立頁面(以 error.html 作例):
<body>
<h1>Oops!</h1>
<p>The page you're trying to access doesn't exist.</p>
<a href="/">back to homepage.</a>
</body>
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "index.html"));
});
/**
* 其他requests處理
*/
//回傳 status code 404 以及回傳error.html
app.get("*", (req, res) => {
res.status(404).sendFile(path.join(__dirname, "error.html"));
});