Day21 NodeJS-Express VI – iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

今天的內容是Express部份的最後一哩路:Restful API與應用程式結構化。前幾天從前端到後端把Express基礎學透透,發現Express並沒有對大型專案的開發預先設計一個良好的結構,若未先設計好程式架構,會讓開發與維護變得很沒有效率 。過去大部份使用.NET MVC進行開發,開發工具建立專案時會自動產生嚴謹的結構,從來沒有想過專案結構設計這件事,是以藉此嘗試在Express框架下設計適當的架構。

Restful API

RESTful API是一種符合REST設計風格且透過網際網路傳輸的API,包含資源的取得、建立、修改與刪除,分別對應HTTP協定的GET、POST、PUT及DELETE方法,通常具有簡潔的URL、不同的資源傳輸類型。

Express中的應用程式結構化

由於Express框架具備高度的開發彈性,像是大量的NPM套件及高度自主的程式架構,為了因應更多樣的開發需求,開發時也必須要考慮如何將程式進行結構化,除了自行規劃架構,在Express中也有提供建立應用程式的工具-express-generator,今天會先說明express-generator的使用方式,再另外嘗試自行規劃MVC架構。

Express-generator與應用程式結構化

在上課程的時候有發現,因為時間久遠的關係,使用express-generator的方法也不太一樣,分成舊版(Node.js 8.2.0版本以前)與新版(Node.js 8.2.0版本以後)說明。

舊版流程

  1. 使用npm install以全域方法安裝express-generator工具。
  2. 在目標資料夾中,透過express <應用程式名稱>可以建立相應的應用程式架構。
  3. npm install指令重建package.json檔案所有相依套件,可以在檔案列表找到node_module及其中安裝好的NPM套件。

新版流程

  1. 在終端機透過npx express-generator指令啟用工具(Node.js 8.2.0版本以上),express-generator會在資料夾路徑內建立一個包含app.jspackage.json和其他資料夾的應用程式架構。
  2. 使用npm install重建所有相依套件,可以在檔案列表找到node_module及其中安裝好的NPM套件。

Express-generator所建立的程式架構以app.js為主程式,並建立一個routes的資料夾,用以存放由路由器(express.Router)建立的模組,並在模組中載入函式及定義路由,再以app.use()方法將模組裝載至主程式的Path,讓程式能具備分層架構,並能依照需求規劃路由器模組與其中的函式及路由。

https://ithelp.ithome.com.tw/upload/images/20211006/20139980MRnD0K554C.jpg

規劃MVC架構

除了透過express-generator建立以Router分層的架構,也可以運用方法模組、樣板等概念建立MVC概念的架構,在前面的文章有規劃public資料夾存放靜態資料、views資料夾存放頁面樣板,今天則是將前面練習的主程式中的方法以頁面和API分為不同的controller模組,也就是MVC中Controller部份的實現。

https://ithelp.ithome.com.tw/upload/images/20211006/20139980on8CaNX3T8.jpg

  1. 建立controllers資料夾,並建立apiController與htmlController兩個*.js檔案。
  2. 分別設定module.exports為包含相應方法的函式,htmlController存放載入頁面相關的方法,apiController存放處理資料的API。
// htmlController
module.exports=(app)=>{
  app.get('/', (req, res)=>{
    res.render("index");
  });

  app.post("/personJson", (req, res)=>{
    res.setHeader('Content-Type', 'application/json');
    res.send(JSON.stringify({ a: "Thank you for the JSON data" }));
    console.log(req.body.fullName);
  });

  app.get("/job/:type", (req, res)=>{
    res.render("job", {TYPE: req.params.type, QSTR: req.query.qstr});
  });
    
  app.post("/person", (req, res)=>{
    res.send("Thank you");
    console.log(req.body.firstName);
    console.log(req.body.lastName);
  });
}
// apiController
module.exports = (app) => {
  app.get("/api/person", (req, res)=>{
    res.json({firstName: "chw", lastName: "k"});
  });

  app.post("/api/person/:id", (req, res)=>{
    // 查詢
  });

  app.delete("api/person/:id", (req, res)=>{
    // 刪除
  });
}
  1. 在主程式透過require()引用模組,並直接呼叫Controller就可以執行其中的功能。
let httpController = require("./controllers/httpController");
let apiController = require("./controllers/apiController");

httpController(app);
apiController(app);
  1. 測試一下確認功能都與原本的程式碼相同,但是就主程式的程式碼而言,變得較簡潔也較易於維護。

https://ithelp.ithome.com.tw/upload/images/20211006/20139980EDI2jVGgeE.png

小結

脫離了完整規劃的.NET後,在使用高度彈性的NodeJS進行開發,才發現應用程式的結構化對於後續的維護很重要,不僅在多人協作的專案中,即使是小專案,沒有架構規劃最後也可能會變成維護時的程式碼地獄。

參考資料

https://expressjs.com/zh-tw/guide/routing.html

Learn and Understand NodeJS [課程]