Previous Page
cover
Node.js
Express.js
Backend
Author: Edison Chue 2021-12-22 12 mins read

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>');
});

_2021-04-13_01.11.58.png

如果web server是爲了製作出API,我們可能會想要把一些Object送到Client side,同樣可以利用send()回傳:

app.get('/', (req, res) => {
    let Object = {
        name: "Edison",
        occupation: "front-end engineer"
    };
  res.send(Object);
});

在瀏覽器打開會是一個JSON格式的物件。

_2021-04-13_01.25.45.png

當我們需要回傳一整個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.");
});

_2021-04-13_19.35.02.png

_2021-04-13_19.34.28.png

_2021-04-13_19.33.40.png

_2021-04-13_19.36.25.png

處理一定pattern的requests:

app.get("/fruits/:somefruit", (req, res) => {
    //req.params能回傳requests的參數物件
  res.send(`You are looking for ${req.params.somefruit}`);
});

_2021-04-13_19.37.27.png

也可以透過object destructuring賦值到獨立變數:

app.get("/fruits/:somefruit", (req, res) => {
    let { somefruit } = req.params
  res.send(`You are looking for ${somefruit}`);
});

_2021-04-13_19.39.06.png

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"));
});

_2021-04-13_19.56.26.png

當使用者按下 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}.`);
});

_2021-04-13_20.06.58.png

_2021-04-13_20.08.19.png

_2021-04-13_20.22.55.png

假設你現在要處理的 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}.`);
})

_2021-04-13_20.27.34.png

導入靜態文件

靜態文件例如 Stylesheet檔案以及影像檔等在 Node.js 的環境下需要作特別的設定,將含有靜態檔案的目錄名稱傳遞給 express.static middleware,就能直接開始提供檔案:

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

並於根目錄建立 public 目錄:

_2021-04-13_20.51.11.png

這時候 index.html 的 link 就能正確指向 public 目錄內的檔案:

<link rel="stylesheet" href="./styles/style.css" />

Styling 亦會正確套入。

_2021-04-13_20.55.15.png

處理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"));
});

_2021-04-13_22.07.04.png