这是我参与更文挑战的第1天,活动详情查看: 更文挑战
一、创键项目
-
创建目录 koa2
-
npm init 创建 package.json,然后执行 npm install
-
通过 npm install koa 安装 koa 模块
-
通过 npm install supervisor 安装supervisor模块, 用于node热启动
-
在根目录下中新建 index.js 文件,作为入口文件, 内容如下:
const Koa = require('koa'); // Koa 为一个class const app = new Koa(); app.use(async (ctx, next) => { await next(); ctx.response.body = 'Hello, koa2!'; }); app.listen(9527, () => { console.log('This server is running at http://localhost:' + 9527) })
6.配置package
{
"name": "koa",
"version": "1.0.0",
"description": "",
"main": "koa.js",
"scripts": {
"serve": "supervisor koa.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"koa": "^2.7.0",
"supervisor": "^0.12.0"
}
}
7 . 启动
npm run serve
二、路由配置
cnpm i koa-router
const router = new Router(); // 实例化路由
router.get('/', async (ctx, next) => {
ctx.response.body = '<h5>好家伙</h5>';
});
app.use(router.routes());
路由参数
//请求地址 www.*****/sss?from=1
router.get('/hello/:name', async (ctx, next) => {
var name = ctx.params.name; // 获取请求参数 sss
var from = ctx.query.from; // 1
ctx.response.body = `<h5>好家伙, ${name}!</h5>`;
});
三、请求
post
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());
router.post('/login', async (ctx, next) => {
let name = ctx.request.body.name;
let password = ctx.request.body.password;
console.log(name, password);
ctx.response.body = `<h4>好家伙, ${name}!</h4>`;
});
get
router.get('/', async (ctx, next) => {
ctx.response.body = '<h4>好家伙</h4>'
});
四、html模板
1、好处
使用html模板,将html从js中分离出去,有助于项目开发和管理。而且,html模板在koa2中,必须通过中间件来实现。
2、koa-views + nunjucks实现html模板
nunjucks.configure(resolve(__dirname, 'views'), { autoescape: true });
app.use(views(__dirname + '/views', {
map: { html: 'nunjucks' }
}));
五、操作静态资源
1、静态资源在开发中的地位
静态资源环境在服务端是十分常用的一种服务,在后台开发中不仅有需要代码处理的业务逻辑请求,也会有很多的静态资源请求。比如请求js,css,jpg,png这些静态资源请求。也非常的多,有些时候还会访问静态资源路径。
2、koa-static-cache实现静态资源操作
app.use(
staticCache(resolve("dist"), {
maxAge: 365 * 24 * 60 * 60
})
)
六、进阶
1、结构
2、结合装饰器decorator写路由
1.依赖安装
2.配置.babelrc
{
"presets": ['react', 'stage-0','env'],
"plugins": [
"transform-runtime",
"transform-decorators-legacy",
"transform-class-properties"
]
}
3.decorator.js
const Router = require('koa-router')
const { resolve } = require('path')
const _ = require('lodash')
const glob = require('glob')
const R = require('ramda')
const symbolPrefix = Symbol('prefix')
const routerMap = new Map()
const isArray = c => _.isArray(c) ? c : [c]
export class Route {
constructor (app, apiPath) {
this.app = app
this.apiPath = apiPath
this.router = new Router()
}
init () {
glob.sync(resolve(this.apiPath, './**/*.js')).forEach(require)
for (let [conf, controller] of routerMap) {
const controllers = isArray(controller)
let prefixPath = conf.target[symbolPrefix]
if (prefixPath) prefixPath = normalizePath(prefixPath)
const routerPath = prefixPath + conf.path
this.router[conf.method](routerPath, ...controllers)
}
this.app.use(this.router.routes())
this.app.use(this.router.allowedMethods())
}
}
const normalizePath = path => path.startsWith('/') ? path : `/${path}`
const router = conf => (target, key, descriptor) => {
conf.path = normalizePath(conf.path)
routerMap.set({
target: target,
...conf
}, target[key])
}
export const controller = path => target => (target.prototype[symbolPrefix] = path)
export const get = path => router({
method: 'get',
path: path
})
export const post = path => router({
method: 'post',
path: path
})
4.routes view.js
const { controller, get } = require('../lib/decorator')
@controller('')
export class viewController {
@get('/')
async home(ctx, next) {
await ctx.render('index', {
})
}
@get('/service')
async enter(ctx, next) {
await ctx.render('service', {
title: '',
})
}
@get('/404')
async pageNUll(ctx, next) {
await ctx.render('404', {
title: ' ',
})
}
}
3、日志文件
cnpm i koa-log4
config/logs.jsvar path = require('path');
//日志根目录
var baseLogPath = path.resolve(__dirname, '../logs')
/*报错输出日志*/
//错误日志目录、文件名、输出完整路径
var errorPath = "/error";
var errorFileName = "error";
var errorLogPath = baseLogPath + errorPath + "/" + errorFileName;
/*请求数据得到响应时输出响应日志*/
//响应日志目录、文件名、输出完整路径
var responsePath = "/response";
var responseFileName = "response";
var responseLogPath = baseLogPath + responsePath + "/" + responseFileName;
/*操作数据库进行增删改等敏感操作记录日志*/
//操作日志目录、文件名、输出完整路径
var handlePath = "/handle";
var handleFileName = "handle";
var handleLogPath = baseLogPath + handlePath + "/" + handleFileName;
/*访问级别日志*/
var accessPath = "/access"
var accessFileName = "access";
var accessLogPath = baseLogPath + accessPath + "/" + accessFileName;
/*访问级别日志*/
var reqPath = "/req"
var reqFileName = "req";
var reqLogPath = baseLogPath + reqPath + "/" + reqFileName;
module.exports = {
//日志格式等设置
appenders:
{
"rule-console": {"type": "console"},
"errorLogger": {
"type": "dateFile",
"filename": errorLogPath,
"pattern": "-yyyy-MM-dd.log",
"alwaysIncludePattern": true,
"encoding": "utf-8",
"path": errorPath
},
"resLogger": {
"type": "dateFile",
"filename": responseLogPath,
"pattern": "-yyyy-MM-dd.log",
"alwaysIncludePattern": true,
"encoding": "utf-8",
// "maxLogSize": 204800,
// "numBackups": 3,
"path": responsePath
},
"handleLogger": {
"type": "dateFile",
"filename": handleLogPath,//生成文件路径和文件名
"pattern": "-yyyy-MM-dd.log",
"alwaysIncludePattern": true,
"encoding": "utf-8",
// "maxLogSize": 204800,
// "numBackups": 3,
"path": handlePath
},
"accessLogger": {
"type": "dateFile",
"filename": accessLogPath,
"pattern": "-yyyy-MM-dd.log",
"alwaysIncludePattern": true,
"encoding": "utf-8",
// "maxLogSize": 204800,
// "numBackups": 3,
"path": accessPath
},
"reqLogger": {
"type": "dateFile",
"filename": reqLogPath,
"pattern": "-yyyy-MM-dd.log",
"alwaysIncludePattern": true,
"encoding": "utf-8",
// "maxLogSize": 204800,
// "numBackups": 3,
"path": reqPath
},
},
//供外部调用的名称和对应设置定义
categories: {
"default": {"appenders": ["rule-console"], "level": "all"},
"resLogger": {"appenders": ["resLogger"], "level": "info"},
"errorLogger": {"appenders": ["errorLogger"], "level": "error"},
"handleLogger": {"appenders": ["handleLogger"], "level": "all"},
"accessLogger": {"appenders": ["accessLogger"], "level": "all"},
"reqLogger": {"appenders": ["reqLogger"], "level": "error"}
},
"baseLogPath": baseLogPath
}
log.js
var log4js = require('koa-log4');
var logsConfig = require('../config/logs.js');
//加载配置文件
log4js.configure(logsConfig);
//调用预先定义的日志名称
var resLogger = log4js.getLogger("resLogger");
var errorLogger = log4js.getLogger("errorLogger");
var handleLogger = log4js.getLogger("handleLogger");
var reqLogger = log4js.getLogger("reqLogger");
var consoleLogger = log4js.getLogger();
exports.accessInfo = () => log4js.koaLogger(log4js.getLogger('accessLogger'));//访问日志
exports.logInfo = (data) => {consoleLogger.info(data)}
.............
.............
3、启动文件 start.js
require('babel-core/register')()
require('babel-polyfill')
require('./server/index.js')
cnpm i
npm start
关于pm2自动部署 webpack打包 以及数据库后续有时间更新
欢迎干饭人一起推动优化
最后附上工具人地址:gitee.com/angry2bird/…