title: koa2+mongodb搭建后台
date: 2018-12-28
categories:
- frontend
tags: - koa2
- mongodb
- nodejs
前言
毫無疑問,目前nodejs里面用來開發后台的首選就是koa2+mongodb的組合了。參考過很多資料,都是零零碎碎不齊全,要么很簡單只是教你如何運行一個demo,要么只講了簡單的一方面,要么就是一個復雜的koa項目生成器,我設想的一個最基礎的后台應該具有以下內容:
此處只討論前后端分離,后台項目提供接口,不考慮模板渲染之類的,畢竟你都用nodejs做后台了,還不做前后端分離也太說不過去了
- 對傳入、返回及錯誤數據做統一處理
- 支持跨域
- 使用 token 做身份驗證
- 完善的日志記錄
- 支持發送郵件
- 上傳文件
- 常見的數據庫操作,對列表數據分頁,返回指定行數據做封裝
- 調試
所以在折騰完之后,就想把整個過程記錄一下,如果你正好是剛開始摸索,應該能讓你避免不少彎路。
創建基礎項目
- 創建koa-mongo目錄,並運行 npm init 創建package.json
mkdir koa-mongo
cd ./koa-mongo
npm init
- 安裝基礎包
npm install koa # koa,必須的
npm install koa-router # 路由,必須的,這里要注意的是還有一個koa-route,這兩個是不同的,不要用koa-route
npm install koa-static # 靜態資源,必須的
- 創建app.js,填入以下內容:
// koa
const Koa = require('koa')
const app = new Koa()
// midleware
const serve = require('koa-static')
app.use(serve('./assets'))
var server = app.listen(3000, function (){
const host = server.address().address;
const port = server.address().port;
console.log('app start listening at http://%s:%s', host, port);
});
此處創建了一個實例,監聽3000端口,將assets目錄作為靜態資源運行,我們創建一個assets目錄,里面創建一個index.html,然后我們運行起來試試:
node ./app.js
此時會打印一行日志:app start listening at http://:::3000,讓我們來訪問試試:

ok,koa啟動一個項目就是這么簡單。。
添加路由
在koa-router的使用說明中,我們可以看到是這樣使用的:
var router = new Router();
router.get('/', (ctx, next) => {
// ctx.router available
});
app
.use(router.routes())
.use(router.allowedMethods());
因為正常項目中,controller肯定不止一個的,所以我把目錄寫成這樣:
├─ controller
├─ test-controller
├─ router.js
controller目錄用來放置所有的controller,在router.js中統一匯總,app.js中只需要使用router.js即可。
test-controller:
const hello = async (ctx, next) => {
ctx.body = 'hello world'
ctx.status = 200;
}
module.exports = {
'test/hello': hello,
}
router.js:
const Router = require('koa-router')
const router = new Router({
prefix: '/api', // 統一前綴,接口全部為 /api/xxx 格式
})
const testController = require('../controller/test-controller')
Object.keys(testController).forEach(key=>{
router.all("/"+key, testController[key]); // router.all是允許所有的訪問方式,如果需要限定則改為指定方式即可
})
module.exports = router;
app.js:
// router
const router = require('./router')
app.use(router.routes()).use(router.allowedMethods())
這個時候讓我們重新啟動一下,訪問localhost:3000/api/test/hello試試:

可以看到正確返回了hello world。
調試
到這里了,有沒有感覺哪里不對勁。每修改一次,都需要手動敲命令重啟一次,這簡直太煩了好嘛,我們程序猿哪能忍受這個。答案就是使用nodemon,這個玩意兒能監聽我們的文件變更,自動運行命令重啟應用。使用方式也很簡單,這個我們直接全局安裝就好了:
npm install -g nodemon
然后去package.json的scripts中添加一行腳本:
"dev": "nodemon ./app.js",
然后 npm run dev,把hello函數修改一下返回值,保存,就會看到nodemon自動幫我們重啟應用了。
除了nodemon,類似的工具還有很多,這里就不展開說了,現在的你只需要知道開發用nodemon,線上用pm2就ok了
解決了自動運行之后,我們來說一下調試。其實nodejs自帶了調試的,只需要一個inspect參數,調試的時候就跟我們在chrome中調試是一模一樣的。
我們先去package.json的scripts中添加一行腳本:
"debug": "nodemon --inspect ./app.js",
然后我們運行 npm run debug,刷新我們的網頁,用f12打開,此時我們能看到開發者工具上面多了一個nodejs的圖標:

點擊這個圖標,就可以跟調試網頁一樣調試nodejs代碼了:

配置化
代碼就是一步步總結,邊寫邊優化,重構。到目前為止,我們會發現有不少配置性的東西是散亂在不同文件中,比如說項目啟動時監聽的端口,接口的統一前綴,考慮到我們還會有很多配置項,我們應該把這些寫到一個配置文件中集中管理。
新建一個config.js:
module.exports= {
port: 3000,
apiPrefix: '/api',
}
然后把用到的地方全部更改為變量
跨域
為了防止跨域問題,我們需要使用koa2-cors類庫,使用方式很簡單:
npm install koa2-cors
然后在app.js中添加以下內容:
const cors = require('koa2-cors')
app.use(cors())
一行代碼搞定,cors的具體配置此處就不細說了,有興趣的可以自己去看看
處理參數,上傳文件
一般來說,我們是使用koa-bodyparser 和 koa-multer來分別處理表單數據和文件數據的。這兩個分別集成也沒什么問題,但我們可以直接使用koa-body來完成。koa-body是基於co-body和formidable做了封裝,同時支持參數解析和文件上傳。最后是把參數和文件分別放到ctx.request.body和ctx.request.files變量中。
我這里是把上傳文件統一放到assets/upload目錄中:
const uploadDir = path.join(__dirname, 'assets/upload/')
// 此處還需要判斷文件夾是否存在,不存在的話就創建
app.use(koaBody({
multipart: true,
encoding: 'utf-8',
formidable:{
uploadDir: uploadDir,
keepExtensions: true,
maxFieldsSize: 5*1024*1024,
onFileBegin:(name, file)=>{
}
}
}))
然后添加一個upload:
const upload = async (ctx, next)=>{
const files = ctx.request.files || {}; # 文件會被解析到ctx.request.files中,是個object
let fileNames = Object.keys(files);
if(fileNames.length<=0){
throw new ApiError('上傳文件不能為空')
}else{
if(fileNames.length===1){
ctx.body = files[fileNames[0]].path.replace(config.baseDir+'/assets', "")
}else {
ctx.body = fileNames.map(key => files[key].path.replace(config.baseDir+'/assets', ""))
}
}
}
token驗證
使用jwt,待續
統一返回格式
待續
mongodb
待續
日志模塊
待續
微信支付
待續
