# 🏅 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 <engine> add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
-c, --css <engine> add stylesheet <engine> 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 連結貼至底下回報就算完成了喔!
解答位置請參考下圖(需打開程式碼的部分觀看)

<!-- 解答:
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)