世界上最伟大的投资就是投资自己的教育
koa2 开发实践指南
1. 介绍
最近用 koa2 来开发应用,把自己的经验记录一下。
介绍 koa 的文章,请查看es6 的 generator 和 nodejs 的下一代框架 koa这篇文章。
2. n 版本管理器
首先使用最新版本的 nodejs。
我使用n来管理 nodejs 的版本,也用 n 来安装比较新的 nodejs。
3. 用 db-migrate 来管理数据库迁移
我想像 rails 那样来管理 migration,只有db-migrate才比较好用。
具体可以查看这篇文章node-db-migrate 入门教程。
4. 用 bookshelf 来作为数据库的 orm
数据库我使用 postgresql,而bookshelf才比较像 rails 的 active_record。
const knex = require('knex')({
client: 'pg',
searchPath: 'public',
connection: {
host : '127.0.0.1',
user : 'hfpp2012',
password : '',
database : 'tspd_dev'
}
});
const bookshelf = require('bookshelf')(knex);
const Repo = bookshelf.Model.extend({
tableName: 'regional_designs'
});
const Koa = require('koa');
const app = new Koa();
// 路由
const Router = require('koa-router');
const router = new Router({
prefix: '/api'
});
// promise写法
router.get('/', function (ctx, next) {
// new Repo({name: 'New Article', created_at: '2016-11-01T03:30:48.351Z', updated_at: '2016-11-01T03:30:48.351Z'}).save().then(function(model) {
// });
return Repo.where('id', 1).fetch().then((json) => {
ctx.body = json;
})
});
5. koa-views 结合 nunjucks 作为模版引擎
koa-views作为 koa 的插件,支持 koa2,它能够支持绝大多数 nodejs 的模版引擎,而我喜欢用 nunjucks 作模版引擎。
类似这样:
var views = require('koa-views');
// Must be used before any router is used
app.use(views(__dirname + '/views', {
map: {
njk: 'nunjucks',
html: 'ejs'
}
}));
router.get('/views', function (ctx, next) {
// return next().then(() => {
// ctx.render('basic.ejs')
// })
ctx.state = {
session: this.session,
title: 'app',
username: 'hfpp2012'
};
// return ctx.render('basic.html')
return ctx.render('test.njk')
});
而test.njk
文件内容为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
{% block header %}
This is the default content
{% endblock %}
<section class="left">
{% block left %}{% endblock %}
</section>
<section class="right">
{% block right %}
This is more content
{% endblock %}
</section>
</body>
</html>
6. 开发环境使用 nodemon 作为启动服务
nodemon可以修改完文件之后自动重启服务。
安装
npm install -g nodemon
7. 使用 koa-logger 来记录日志
koa 默认没啥日志,[koa-logger] 又支持 koa2,所以用它来显示日志。
// 日志
const logger = require('koa-logger');
app.use(logger());
8. 用 koa-router 来作为路由控件
写一个应用,总要暴露路由给人用。koa-router支持 koa2,又比较好用。
// 路由
const Router = require('koa-router');
const router = new Router({
prefix: '/api'
});
router.post('/regional_design/repos.json', function (ctx, next) {
let json = {"id":11,"name":"新的药库","pos_x":null,"pos_y":null,"parent_id":null,"drug_id":null,"created_at":"2016-12-23T03:16:58.728Z","updated_at":"2016-12-23T03:16:58.728Z"};
ctx.body = json;
});
router.get("/regional_design/repos/:id(\\d+).json", function (ctx, next) {
let json = {"name":"西药库","type":"RegionalDesign::Repo","children_object_type":"drug_repo","children":[{"id":5,"name":"药库","initialPos":{"x":73,"y":54}},{"id":6,"name":"药库","initialPos":{"x":276,"y":120}}]};
ctx.body = json;
});
9. 使用 koa-send 发送静态文件
有时候需要直接提供 html 文件,或 js css 静态文件,在生产环境下可能可以直接使用 nginx 来读取,但是在开发环境下也可以用koa-send跟生产环境下保持一致。
var send = require('koa-send');
app.use(async function (ctx, next){
await send(ctx, ctx.path, { root: __dirname + '/public' });
})
10. koa2 的三种函数写法
第一种是最常见的写法,使用 promise。
// promise写法
router.get('/', function (ctx, next) {
// new Repo({name: 'New Article', created_at: '2016-11-01T03:30:48.351Z', updated_at: '2016-11-01T03:30:48.351Z'}).save().then(function(model) {
// });
return Repo.where('id', 1).fetch().then((json) => {
ctx.body = json;
})
});
第二种使用 co 库的写法:
// co写法
const co = require('co');
router.get('/', co.wrap(function *(ctx, next) {
ctx.body = yield Repo.where('id', 1).fetch();
}));
第三种:async/await 写法
router.get('/', async (ctx, next) => {
ctx.body = await Repo.where('id', 1).fetch();
});
最后一种写法需要用 babel 来转化源码,转成 node 可以读取的代码。
使用babel-plugin-transform-async-to-generator这个插件就可以转化。
// .babelrc
{
"plugins": ["transform-async-to-generator"]
}
// package.json
"scripts": {
"start": "nodemon index.js",
"build": "babel index.js --out-file main.js",
"babel-start": "nodemon --exec babel-node index.js"
},
11. 使用 shipit 和 pm2 来部署应用
shipit是全自动化部署脚本,有点类似于 ruby 的capistrano,使用它,以后只要一行命令就可以自动完成部署。
在生产环境下使用pm2来管理 nodejs 的进程。
部署脚本示例:
// shipitfile.js
module.exports = function (shipit) {
require('shipit-deploy')(shipit);
require('shipit-npm')(shipit);
require('shipit-shared')(shipit);
// require('shipit-db')(shipit);
// require('shipit-assets')(shipit);
shipit.initConfig({
default: {
workspace: './.deploy_build',
deployTo: '/home/hfpp2012/koa-app-start',
repositoryUrl: 'git@git.oschina.net:hfpp2012/koa-app-start.git',
branch: 'master',
ignores: ['.git', 'node_modules'],
rsync: ['--del'],
keepReleases: 2,
shallowClone: true,
shared: {
overwrite: true,
dirs: ['public/uploads'],
files: ['database.json',
{
path: 'database.json',
overwrite: false,
chmod: '755',
}
]
}
},
production: {
servers: 'hfpp2012@koa.rails365.net'
}
});
shipit.task('install-db-migrate', function () {
return shipit.remote('sudo npm install -g db-migrate');
});
shipit.task('db-migrate', function () {
return shipit.remote('cd /home/hfpp2012/koa-app-start/current && db-migrate up -e prod');
});
shipit.on("published", function(){
shipit.start("db-migrate");
});
require('shipit-pm2')(shipit);
// shipit.task('pm2', function () {
// return shipit.remote('cd /home/hfpp2012/koa-app-start/current && pm2 startOrRestart ./app.json --env production');
// });
};
以后可以使用一行命令来部署:
shipit production deploy
参考资料:使用 Shipit+Gulp+PM2+Nginx 自动部署 Nodejs 应用
nginx 配置示例如下:
upstream my_nodejs_upstream {
server 127.0.0.1:3001;
keepalive 64;
}
server {
listen 80;
server_name koa.rails365.net;
root /home/hfpp2012/koa-app-start/current/public;
try_files $uri/index.html $uri @koa;
location @koa {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_max_temp_file_size 0;
proxy_pass http://my_nodejs_upstream;
proxy_redirect off;
proxy_read_timeout 240s;
}
}
参考链接:
完结。
本站文章均为原创内容,如需转载请注明出处,谢谢。
© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn
粤公网安备 44152102000088号 | 粤ICP备19038915号
Top