### GDSC NYUST x 資訊創客社 <br> ### JS後端與資料庫讀書會 #### Express 課程 <br> #### 2023/11/15 ( Wed ) 19:00 - 21:00 #### 講師:蘇祐民 *YoMin Su* #### 本次課程影片:(⚒️製作中) <img src="" height="200px"> --- ## 課程簡介 ---- ### 簡單的說 - 認識Express - 建立自己的Express應用程式 - 部屬Express應用程式 ---- ### 複雜點講 - 認識Express - 建立Node專案並安裝Express - 建立基本Express應用 - 如何定義Express路由 - 設計Express Middleware - 透過Express實作RESTful API - 整合資料庫(SQLite) - 部署Express與設定網頁伺服器 --- ## 初見 Express.js ---- ### Express 是誰設計的? 原作者是<span class="orange">TJ Holowaychuk</span>,他同時也是另一個有名的框架,<span class="bluegreen">Koa</span>的作者,所以這兩者可謂系出同源! 在經過幾次的管理轉移後,目前Express是由Node.js基金會負責管理~ > Express也被稱為是Node.js的伺服器框架的『事實標準』 ---- ### Express 可以做什麼? - 後端邏輯處理 - 網頁伺服器 - 檔案下載網站 - etc... > 基本上透過HTTP請求的方式,都是可以的 ---- ### 今日目標 - 寫個簡單的Express範例 - 嘗試串接SQLite資料庫 - 將Express與網頁伺服器整合 --- ## 建立Node.js專案 ---- ### 找個喜歡的資料夾 ![image](https://hackmd.io/_uploads/H1ki5xMVa.png) ---- ### 初始化專案 ![image](https://hackmd.io/_uploads/r1Uhqez46.png) ---- ### 將Express加入到專案中 ![image](https://hackmd.io/_uploads/ByUC9gM4p.png) --- ## 來寫應用吧 ---- ### 先新增個檔案 ![image](https://hackmd.io/_uploads/r1qPpezEp.png) ---- ### 基本程式碼 ```javascript= const express = require('express'); let app = express(); app.get('/', (req, res, next) => { res.status(200).send('Hello!'); }); app.listen(3000, () => { console.log("Express is running!"); }); ``` ---- ### 剛剛那個在幹嘛? - app: 建立Express的實例 - app.get(): 讓Express透過GET方法進行監聽 - app.listen(): 在系統上哪個位置工作 ---- ### 如何處理路由? 路由也可以被稱為資源路徑,是用於區分不同內容的功能! 在Express中,有兩種方式可以使用,分別來說明~ ---- ### 標準用法 ```javascript= app.get('url'); app.post('url'); app.put('url'); /*或是*/ app.patch('url'); app.delete('url') ``` 以上四種都是基本可以使用的方式,在url的字串欄位填入你希望的路徑就可以了! Example: ```javascript= app.get('/'); app.post('/user'); app.delete('/user/topic'); ``` ---- ### 標準的延伸 ```javascript= app.route('/url') .get((req, res) => {}) .post((req, res) => {}) .delete((req, res) => {}); ``` 透過.route方法,可以直接幫指定的路徑加上對應的HTTP Method ---- ### 第二種方式 透過express.Router是另一種可以達到相同效果的作法,若需要比較容易維護的架構,可以考慮這種方式: ```javascript= const express = require('express'); var router = express.Router(); router.use(/*Code here*/); router.get(/*Code here*/); router.post(/*Code here*/); module.exports = router; ``` ---- ### 第二種方式(2) 上面為router本身,接著要在主要檔案中引入 ```javascript= const express = require('express'); let app = express(); const paths = require('./filename.js'); app.use('/path', paths); ``` ---- ### 中介層 當你希望在路由進入前做點什麼,或是在離開後做點什麼,就會用到它 Example: ```javascript= const express = require('express'); let app = express(); app.use((req, res, next) => { console.log("Something happened: ", Date.now()); next(); }); app.get(/*Code here*/); app.use((error, req, res, next) => { console.log("Error out: ", error); }); ``` ---- ### 若希望幫中介層加入參數 可以透過return function的方式使用,範例如下 ```javascript= function middle(aaa, bbb) { return (req, res, next) => { console.log(aaa, bbb); } } app.use(middle('123', 'abc')); ``` --- ## RESTful API ---- ### 簡介 就像我們在期中考前所提到的: - Uniform Interface:統一介面。 - Stateless:無狀態。 - Cacheable:可快取。 - Client-Server:客戶伺服器分離模式,任何一個客戶端與伺服器都是可替換的。 - Layered System:分層的系統,客戶端不知道他聯絡的是不是最終伺服器。 ---- ### 在Express中實作 我們可以透過標準的幾個HTTP方法達到RESTful的格式,範例如下: ```javascript= const express = require('express'); let app = express(); let person = []; app.use(express.urlencoded()); app.use(express.json()); app.route('/user') .get((req, res) => { res.status(200).send(person.toString()) }) .post((req, res) => { console.log(req.body); person.push(req.body.person); res.status(200).send('Add Success'); }) .patch((req, res) => { res.status(200).send('Method not work'); }) .delete((req, res) => { person = person.filter(p => p != req.body.person); res.status(200).send("Delete Success") }); app.listen(3000, () => { console.log("Express is running!"); }); ``` ---- ### 測試時間 取得資料內容: ```bash= curl localhost:3000/user ``` 加入一筆紀錄: ```bash= curl -X POST -H "Content-Type: application/json" --data '{"person":"YoMin"}' localhost:3000/user ``` 修改紀錄: ```bash= curl -X PATCH localhost:3000/user ``` 刪除一筆紀錄: ```bash= curl -X DELETE -H "Content-Type: application/json" --data '{"person":"YoMin"}' localhost:3000/user ``` --- ## 來個資料庫吧 ---- ### 安裝SQLite ![image](https://hackmd.io/_uploads/r1DmNzzN6.png) ---- ### 來改寫剛剛的範例 ```javascript= const express = require('express'); let app = express(); const dbFile = './person.db'; const sqlite = require('sqlite3').verbose(); let db = new sqlite.Database(dbFile); db.serialize(() => { db.run("CREATE TABLE person (name TEXT)"); }); app.use(express.urlencoded()); app.use(express.json()); app.route('/user') .get((req, res) => { let person = ''; db.serialize(() => { db.each("SELECT name FROM person", (err, row) => { res.status(200).send(row.name); }); }); }) .post((req, res) => { db.serialize(() => { db.run("INSERT INTO person VALUES (?)", [req.body.person]); }); res.status(200).send('Add Success\n'); }) app.listen(3000, () => { console.log("Express is running!"); }); ``` ---- ### 測試時間 取得資料內容: ```bash= curl localhost:3000/user ``` 加入一筆紀錄: ```bash= curl -X POST -H "Content-Type: application/json" --data '{"person":"YoMin"}' localhost:3000/user ``` --- ## 串接網頁伺服器 ---- ### 拿nginx作為範例 ```nginx= server { listen 80 default_server; listen [::]:80 default_server; server_name _; location / { proxy_pass http://127.0.0.1:3000; } } ``` ---- ### 重新啟動網頁伺服器 ```bash= sudo service nginx restart ``` ---- ### 改透過網頁伺服器確認是否可以連線 ```bash= curl localhost/user ``` --- ## 課程回顧 | Q&A ---- ### 今天了解到 - Express基礎 - Express路由 - Express中介層 - CRUD操作 - 串接SQLite - 透過網頁伺服器反向代理 ---- ### Q & A 有任何問題嗎? ---- ### 學習資源 - [MDN](https://developer.mozilla.org/zh-TW/docs/Learn/Server-side/Express_Nodejs) - [Express.js](https://expressjs.com/zh-tw/) --- ## Bye Bye ![image](https://hackmd.io/_uploads/rJRoAMG4T.png) <style> .orange { color: #FF8800; } .red { color: #FF0000; } .bluegreen { color: #00FFCC; } .gray { color: #272727; } .blue { color: #00E3E3 } </style>
{"title":"建立現代後端應用程式入門","slideOptions":"{\"transition\":\"concave\",\"allottedMinutes\":100}","description":"YoMin Su","contributors":"[{\"id\":\"f8142aa2-66aa-4867-821d-2f1ffff7a7ba\",\"add\":6388,\"del\":27}]"}
    190 views
   Owned this note