# 🏅 Day 16 - Express 應用程式產生器(Express generater)、在 routes 設計路由 express 應用程式產生器可以快速產生一個應用程式架構 安裝步驟 - 先開好一個新專案 - 執行 `npm install express-generator -g` - 接著切換到專案路徑下,執行 `express --no-view` 可參考[文件](https://expressjs.com/zh-tw/starter/generator.html)查看指令選項 注意:這裡需要選擇 `no view`,因最終作業最後設計出的 API 只需要回傳 JSON 資料,不會使用到 view 模板引擎 :::spoiler 指令選項 ``` $ express -h Usage: express [options][dir] Options: -h, --help output usage information --version output the version number -e, --ejs add ejs engine support --hbs add handlebars engine support --pug add pug engine support -H, --hogan add hogan.js engine support --no-view generate without view engine -v, --view &lt;engine&gt; add view &lt;engine&gt; support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade) -c, --css &lt;engine&gt; add stylesheet &lt;engine&gt; support (less|stylus|compass|sass) (defaults to plain css) --git add .gitignore -f, --force force on non-empty directory ``` ::: 執行成功後應該會出現以下結構 :::spoiler 資料夾結構 ``` ├── app.js ├── bin │ └── www ├── package.json ├── public │ ├── images │ ├── javascripts │ ├── stylesheets │ │ └── style.css │ └── index.html └── routes ├── index.js └── users.js ``` ::: 此結構已將 routes 的部分拆成獨立模組,並在 app.js 引入 在 routes 的 index.js 或 users.js,會使用 `const router = express.Router()` 並使用 `router` 來設定路由 app.js 引入 ```javascript= const usersRouter = require('./routes/users'); app.use('/users', usersRouter); ``` ./routes/users.js ```javascript= const express = require('express'); const router = express.Router(); router.get('/', function(req, res, next) { res.send('respond with a resource'); }); module.export = router; ``` > 需注意在 app.js 引入使用時,就會自動帶入 `/users`,因此 users.js 中 path 可直接從 `/users` 之後開始( 第 4 行:`router.get('/', ...)` 就會是 `/users`) 第一次啟用伺服器時需執行 `npm install` 安裝相關套件,並執行 `npm start` 若想使用 nodemon 運行也可自行在 package.json 加上指令,並使用 `npm run start:dev` 運行 ```json "scripts": { "start": "node ./bin/www", "start:dev": "nodemon ./bin/www" } ``` ### 參考資源 - [Express 應用程式產生器](https://expressjs.com/zh-tw/starter/generator.html) - [Express - API](http://expressjs.com/zh-tw/api.html#express.router) - 課程影音「Express - Node.js Web 應用程式架構」 題目 --- 請嘗試建立一個 express 專案使用 express generater 產生結構,並完成以下需求 1. 在 app.js 載入 mongoose 並連接至 database(database 名稱可自行設定) 2. 建立 Post Model 連接 Post collection 與 postSchema(拆分至 `./models/posts.js` ) 3. 將 postsRouter 拆分至 ./routes/posts.js 內設計取得所有貼文與新增貼文的路由 - 取得所有貼文 GET,200 成功回傳 `status: 'success'` 與貼文資料(運用到 mongoose 查詢資料) - 新增貼文 POST,200 成功回傳 `status: 'success'` 與 `message: '新增成功'`(運用到 mongoose 新增資料) 4. 在 app.js 引入 postsRouter app.js ```javascript= var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan'); /* 載入 mongoose 並連接至 database(database 名稱可自行設定) */ ... var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users'); /* 引入 postsRouter */ ... var app = express(); app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', indexRouter); app.use('/users', usersRouter); /* 使用 postsRouter */ ... module.exports = app; ``` ./models/posts.js ```javascript= /* 建立 Post Model 連接 Post collection 與 postSchema */ ... ``` > :::spoiler 可直接使用此簡易 schema 範例(或是自行依照作業設計稿設計) > ``` > const postSchema = new mongoose.Schema({ > content: { > type: String, > required: [true, '貼文內容未填寫'] > }, > image: { > type: String, > default: '' > }, > createdAt: { > type: Date, > default: Date.now, > select: false > }, > likes: { > type: Number, > default: '' > } > }, { versionKey: false }); > ``` > ::: <br> ./routes/posts.js ```javascript= /* 設計取得所有貼文、新增貼文的路由 */ ... ``` ## 回報流程 將答案寫在 CodePen 並複製 CodePen 連結貼至底下回報就算完成了喔! 解答位置請參考下圖(需打開程式碼的部分觀看) ![](https://i.imgur.com/vftL5i0.png) <!-- 解答: app.js ```javascript= /* 載入 mongoose 並連接至 database(database 名稱可自行設定) */ const mongoose = require('mongoose'). mongoose.connect('mongodb://localhost:27017/testPost'); /* 引入 postsRouter */ const postsRouter = require('./routes/posts.js') /* 使用 postsRouter */ app.use('/posts', postsRouter); ``` ****************** ./models/posts.js ```javascript= const mongoose = require('mongoose'); const postSchema = new mongoose.Schema({ content: { type: String, required: [true, '貼文內容未填寫'] }, image: { type: String, default: '' }, createdAt: { type: Date, default: Date.now, select: false }, likes: { type: Number, default: '' } }, { versionKey: false }); const Post = mongoose.model('Post', postSchema); module.exports = Post; ``` ****************** ./routes/posts.js ```javascript= const express = require('express'); const router = express.Router(); const Post = require('../models/posts'); // 取得所有貼文 router.get('/', async (req, res) => { const allPosts = await Post.find(); res.status(200).json({ status: 'success', data: allPosts }) }); // 新增貼文 router.post('/', async (req, res) => { const postData = req.body; const allPosts = await Post.create(postData); res.status(200).json({ status: 'success', message: '新增成功' }) }); module.exports = router; ``` --> 回報區 --- <!-- 將答案貼至下方表格內,格式: | Discord 暱稱 | [CodePen](連結) | --> | Discord | CodePen / 答案 | |:-------------:|:-----------------:| | xxx | [CodePen]() | | 苡安 | [hackmd](https://hackmd.io/@L7K9-66lSeagS28AP0_GjQ/HkwnyVDZC) | | Chia Pin | [CodePen](https://codepen.io/joker-cat/pen/VwNgVrq) | | jenny7532 | [CodePen](https://codepen.io/wei-chen-wu/pen/qBwgQjK#_=_) | | Lobinda | [HackMD](https://hackmd.io/@Lobinda/S1GwoYDZC) | | wei | [HackMD](https://hackmd.io/ET0OOWI4T66UO_eTasYjhQ?view) | | Aida | [CodePen](https://codepen.io/ada23410/pen/eYoxobX?editors=0010) | | ej_chuang | [CodePen](https://codepen.io/EJChuang/pen/gOyEXoJ) | | william_hsu | [CodePen](https://codepen.io/william8815/pen/xxeBPWW) | | Tiya | [CodePen](https://codepen.io/Tiya_blank/pen/rNbQPbY) | | Ciel | [CodePen](https://codepen.io/nycteachen/pen/NWmmRJa) | | tung030374 | [CodePen](https://codepen.io/tung__u/pen/ExJJRej) | | Henry | [HackMD](https://hackmd.io/htzJ8rbKTSmu71Nd7Wf7OQ) | | Hank | [CodePen](https://codepen.io/tw1720/pen/dyLrzNx) | | Fabio20 | [CodePen](https://codepen.io/fabio7621/pen/mdgYqJq) | | william威良 | [CodePen](https://codepen.io/snowman12320/pen/ExJzbPP?editors=1010) | | 2魚 | [CodePen](https://codepen.io/ijrekmsn-the-sans/pen/JjVQPvP) | | 瑀君 |[HackMD](https://hackmd.io/@sh5ojkmt/rJ8u6WWMC)| |Mei|[HackMd](https://hackmd.io/WNpQWt3JTY2hqacXHAAjjg?view)| |Benson|[CodePen](https://codepen.io/nosneb83/pen/bGJyYjJ)| | albertyang3576 | [CodePen](https://codepen.io/albertyang3576/pen/eYowXOx)| | runweiting | [CodePen](https://codepen.io/weiting14/pen/ZEZgLpw)| | zaoannihao | [CodePen](https://codepen.io/ckhwdvrx-the-solid/pen/OJYyKwW)| |Theodore0602|[Codepen](https://codepen.io/GustavoFringgg/pen/WNBpYOo?editors=0010)