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


Posted in Javascript onDecember 11, 2020

一、创键项目

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、结构

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

入口文件(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

到此这篇关于node koa2 ssr项目搭建的方法步骤的文章就介绍到这了,更多相关node koa2 ssr项目搭建内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
JavaScript 实现模态对话框 源代码大全
May 02 Javascript
jquery next nextAll nextUntil siblings的区别介绍
Oct 05 Javascript
jquery的trigger和triggerHandler的区别示例介绍
Apr 20 Javascript
js实现同一个页面多个渐变效果的方法
Apr 10 Javascript
JS+CSS实现简单滑动门(滑动菜单)效果
Sep 19 Javascript
Jquery Easyui日历组件Calender使用详解(23)
Dec 18 Javascript
jquery实现tab选项卡切换效果(悬停、下方横线动画位移)
May 05 jQuery
Vue组件之极简的地址选择器的实现
May 31 Javascript
Vue.js 使用v-cloak后仍显示变量的解决方法
Nov 19 Javascript
js实现unicode码字符串与utf8字节数据互转详解
Mar 21 Javascript
JavaScript实现单英文金山打字通
Jul 24 Javascript
javascript代码简写的几种常用方式汇总
Aug 23 Javascript
uni-app 自定义底部导航栏的实现
Dec 11 #Javascript
微信小程序实现音乐播放页面布局
Dec 11 #Javascript
JS实现可以用键盘方向键控制的动画
Dec 11 #Javascript
JS实现京东商品分类侧边栏
Dec 11 #Javascript
vue使用exif获取图片经纬度的示例代码
Dec 11 #Vue.js
vue使用exif获取图片旋转,压缩的示例代码
Dec 11 #Vue.js
一行JavaScript代码如何实现瀑布流布局
Dec 11 #Javascript
You might like
PHP中使用smarty生成静态文件的例子
2014/04/24 PHP
php集成环境xampp中apache无法启动问题解决方案
2014/11/18 PHP
php实现mysql数据库分表分段备份
2015/06/18 PHP
Yii2验证器(Validator)用法分析
2016/07/23 PHP
PHP读取大文件的几种方法介绍
2016/10/27 PHP
PHP数组式访问接口ArrayAccess用法分析
2017/12/28 PHP
事件模型在各浏览器中存在差异
2010/10/20 Javascript
js 获取浏览器版本以此来调整CSS的样式
2014/06/03 Javascript
js自动生成的元素与页面原有元素发生堆叠的解决方法
2014/09/04 Javascript
JavaScript中的定时器之Item23的合理使用
2015/10/30 Javascript
JS+CSS实现鼠标经过弹出一个DIV框完整实例(带缓冲动画渐变效果)
2016/03/25 Javascript
Jquery实现$.fn.extend和$.extend函数
2016/04/14 Javascript
JS操作xml对象转换为Json对象示例
2017/03/25 Javascript
Vue打包后出现一些map文件的解决方法
2018/02/13 Javascript
vue移动端使用canvas签名的实现
2020/01/15 Javascript
JS面向对象编程——ES6 中class的继承用法详解
2020/03/03 Javascript
VUE+elementui组件在table-cell单元格中绘制微型echarts图
2020/04/20 Javascript
基于js实现的图片拖拽排序源码实例
2020/11/04 Javascript
ES6的循环与可迭代对象示例详解
2021/01/31 Javascript
[03:32]2014DOTA2西雅图邀请赛 CIS外卡赛赛前black专访
2014/07/09 DOTA
[01:30:15]DOTA2-DPC中国联赛 正赛 Ehome vs Aster BO3 第二场 2月2日
2021/03/11 DOTA
python中getaddrinfo()基本用法实例分析
2015/06/28 Python
python中的字典操作及字典函数
2018/01/03 Python
python实现批量解析邮件并下载附件
2018/06/19 Python
Python使用numpy模块创建数组操作示例
2018/06/20 Python
matplotlib.pyplot绘图显示控制方法
2019/01/15 Python
opencv+python实现鼠标点击图像,输出该点的RGB和HSV值
2020/06/02 Python
Python3中对json格式数据的分析处理
2021/01/28 Python
如何判断计算机可能已经中马
2013/03/22 面试题
新闻学专业应届生求职信
2013/11/08 职场文书
恐龙的灭绝教学反思
2014/02/12 职场文书
警察先进个人事迹材料
2014/05/16 职场文书
数学教育专业求职信
2014/07/22 职场文书
乡镇消防安全责任书
2014/07/23 职场文书
MySQL中in和exists区别详解
2021/06/03 MySQL
JavaWeb Servlet开发注册页面实例
2022/04/11 Java/Android