当前位置:主页 > 脚本语言 > NodeJS >

node koa2 ssr项目搭建的方法步骤

时间:2021-06-04 07:55:13 | 栏目:NodeJS | 点击:

一、创键项目

1.创建目录 koa2

2.npm init 创建 package.json,然后执行 npm install

3.通过 npm install koa 安装 koa 模块

4.通过 npm install supervisor 安装supervisor模块, 用于node热启动

5.在根目录下中新建 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、结构

入口文件(index.js)

const Koa = require('koa')
const bodyParser = require('koa-bodyparser');
const staticCache = require('koa-static-cache');
const views = require('koa-views')
const {resolve} = require('path')
const R = require('ramda')
const MIDDLEWARES = ['router'] //中间件配置文件
const nunjucks = require('nunjucks')
const logsUtil = require('../utils/logs.js');

//中间件导入 路由导入
const useMiddlewares = (app) => {
 R.map(
 R.compose(
  R.forEachObjIndexed(
  initWith => initWith(app)
  ),
  require,
  name => resolve(__dirname, `./middlewares/${name}`)
 )
 )(MIDDLEWARES)
}

;(async () => {
 const app = new Koa();
 // view engine setup
 nunjucks.configure(resolve(__dirname, 'views'), { autoescape: true });
 //views with nunjucks
 app.use(views(__dirname + '/views', {
  map: { html: 'nunjucks' }
 }));
 app.use(bodyParser());
 app.use(logsUtil.accessInfo()); //访问日志

 //静态资源配置缓存
 app.use(
   staticCache(resolve("dist"), {
    maxAge: 365 * 24 * 60 * 60
  })
 )
 
 app.on('error', err => {
 
 });

 app.use(async (ctx,next) => {
   await next()
  if(parseInt(ctx.status) === 404){
  ctx.response.redirect("/404")
 }
 
 });
  await useMiddlewares(app) //导入中间件

  app.listen(9527,() => {
 console.log('Server running on port %d', 9527);
 })
})()

2、路由中间件封装

   1.新建middlewares文件夹   在下面新建router.js
   2.新建lib文件夹 在下面新建decorator.js
   3.新建routes下面新建views.js

router.js

const { Route } = require('../lib/decorator')
const { resolve } = require('path')

export const router = app => {
 const apiPath = resolve(__dirname, '../routes')
 const router = new Route(app, apiPath);
 router.init()
}

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
})

export const put = path => router({
 method: 'put',
 path: path
})

export const del = path => router({
 method: 'delete',
 path: path
})

export const use = path => router({
 method: 'use',
 path: path
})

export const all = path => router({
 method: 'all',
 path: path
})

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)}
.............
.............

关于pm2自动部署   webpack打包  以及数据库后续有时间更新

欢迎干饭人一起推动优化

最后附上工具人地址:https://gitee.com/angry2bird/node-koa

您可能感兴趣的文章:

相关文章