學了一段時間的 js 了,忽然想實踐一下。正好公司有個小的項目要作,就順手拿 Koa2 來作了。真是不作不知道,作了想不到。踩了一堆新手坑。javascript
在知道 Koa2 以前,我也瞭解過 Express,惋惜並無實戰用過。後來你們都說 Koa 是一個比 Express 更牛X的東西,因而在好(做)奇(死)心做祟下,直接去用 Koa2 了。後來證實的確是做死,本來用 PHP 一天就能寫完東西,愣是讓我搞了三天。html
最近 Node.js V8 發佈了,原生支持 async
和 await
調用了,因此直接把 Node.js 升級了一下。java
根據 Koa2 的教程,安裝很簡單,我是使用的 yarn 的(還真是比 npm 快)。node
yarn add koa
默認就裝了 Koa 2.2。而後裝完了,其實我是一臉懵逼的,文檔上說這樣用。git
const Koa = require('koa') const app = new Koa() // response app.use(ctx => { ctx.body = 'Hello Koa' }) app.listen(3000)
我照着代碼寫了下來,的確成功了。但是,難不成我要把全部的邏輯寫在 app.use
裏?github
我感受我受到了驚嚇,嚇得我趕忙往下看文檔。原來 Koa2 是一箇中間件模型。app.use
能夠有不少,每個 app.use
會註冊一箇中間件,這個中間件是具體作事情的。每一箇中間件是依次執行的。一個經典的洋蔥圖能夠解釋這一切。npm
那麼,上面的實例就能夠改形成這樣。json
app.use(async (ctx, next) => { await next() ctx.body = 'Hello Koa' })
按照上面的洋蔥頭,以心爲單位,next的兩側的語句分別在洋蔥的左側和右側進行執行,頗像 Laravel
的中間件。bash
就這樣,我知道了,全部的操做沒必要寫在同一個 app.use
裏。但是,下一個問題來了,我要把全部的邏輯都寫再一個文件裏?說好的 MVC 呢?沒有 MVC 也叫作框架?Are you kidding me?(好吧後來發現原來 Koa2 並非一個裝置作網站的框架)app
既然沒有 MVC,那就本身動手豐衣足食吧。
首先要處理的就是路由的問題。不過,因爲是第一次用這貨寫項目,時間緊,(僞)任務重,看了文檔後發現,原來還有一箇中間件列表的連接,裏面有各類開源的中間件。我想大家必定隔着屏幕都能聽到我發出槓鈴般的笑聲了。有一箇中間件很是棒,叫作 koa-router。這貨是這麼用的。
var Koa = require('koa') var Router = require('koa-router') var app = new Koa() var router = new Router() router.get('/', function (ctx, next) { // ctx.router available }); app.use(router.routes())
雖然是把邏輯和 app.use
分開了,可是,好像仍是沒有解決剛纔的問題。說好的 MVC 也沒有出現。因而我再去找了找,竟然沒有 Controller
的中間件。我一下就懵逼了,玩脫了?還有一天啊個人寶貝兒。通過我半秒鐘的慎重思考,我仍是用 koa-router
本身實現一個控制器吧。
const fs = require('fs') function addRoutes(router, routes) { for (let route in routes) { switch (route.method) { case: 'post': router.post(route.uri, route.fn) console.log(`Register post url: ${route.uri}`) break case: 'get': router.get(route.uri, route.fn) console.log(`Register get url: ${route.uri}`) break default: console.log(`Invalid url: ${route}`) } } } function addControllers(router) { let files = fs.readdirSync(__dirname + '/controllers') let controllerFiles = files.filter(f => { return f.endsWith('.js') }) for (let controllerFile in controllerFiles) { console.log(`process controller: ${controllerFile}...`) let routes = require(__dirname + '/controllers') addRoutes(router, routes) } } module.exports = () => { let router = require('koa-router')() addControllers(router) return router.routes() }
我經過在 controllers
文件夾中,建立若干 js
文件來做爲 Controller
來使用。這裏稍微參考了下 廖雪峯的文章。
而後,咱們只須要在 controllers
文件夾中添加合適的文件就能夠了。例如咱們添加一個文件叫作 chart.js
,而後這樣寫代碼。
let hello = async (ctx, next) => { ctx.body = 'Hello the fucking world!' } module.exports = [ { method: 'get', uri: 'hello', fn: hello, } ]
最後再在 app.js
註冊中間件便可。
除此以外,咱們還須要可以處理 ctx
裏的內容,由於它裏面存儲的是原始的內容。仍是因爲時間緊,任(填)務(坑)重(急),我用了 koa-bodyparser。
const bodyParser = require('koa-bodyparser') app.use(bodyParser())
這裏要提醒的是,這貨必定要放在處理路由中間件的前面。
MVC
的 C
已經解決了,接下來就要解決 M
的問題了。這裏我用的是 Sequelize。這個 ORM
和大多數的 ORM
都差很少,因此在這裏此次沒有踩到什麼坑。我在根目錄下新建了一個 config.js
的配置文件,而後新建了 model.js
用來定義模型。
const Sequelize = require('sequelize') const config = require('./config').databases ... module.exports = { //models }
視圖,我是使用了一箇中間件叫作 koa-view。因爲它使用的是 Nunjucks 模板引擎,對於寫 PHP
的我相對熟悉一點。
const view = require('koa-view') const app = Koa() app.use(view(__dirname + '/views'))
//controller let Hello = (ctx, next) => { ctx.render('hello', datas) }
只要在 'views' 文件夾中定義相對應的 html 文件便可。
此次的嘗試,終於在個人修修補補中,搞出了一個簡陋的 MVC
模型。趕在了 deadline 前完成,真是一波三折啊。學習新技術,就是這樣,要實踐嘛= =下面給出個人項目目錄做參考
koa2/ | +- controllers/ | | | +- chart.js | ... | +- static/ | | | +- js/ | ... | | | +- style/ | | | +- img | ... | +- views/ | | | +- game.html | ... | +- app.js | +- config.js | +- controller.js | +- model.js | +- package.json | +- yarn.lock | +- node_modules/
菜鳥做品,若有錯誤請指正,不勝感激。
若是你喜歡個人文章,那就請我喝杯奶茶吧~