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 相关文章推荐
js获取某元素的class里面的css属性值代码
Jan 16 Javascript
JavaScript操作Cookie详解
Feb 28 Javascript
基于jQuery倾斜打开侧边栏菜单特效代码
Sep 15 Javascript
JavaScript中的Reflect对象详解(ES6新特性)
Jul 22 Javascript
JS 拦截全局ajax请求实例解析
Nov 29 Javascript
基于jQuery实现简单人工智能聊天室
Feb 10 Javascript
JS去掉字符串前后空格、阻止表单提交的实现代码
Jun 08 Javascript
JS中的三个循环小结
Jun 20 Javascript
使用bootstraptable插件实现表格记录的查询、分页、排序操作
Aug 06 Javascript
angularjs手动识别字符串中的换行符方法
Oct 02 Javascript
原生javascript单例模式的应用实例分析
Feb 23 Javascript
jQuery class属性操作addClass()与removeClass()、hasClass()、toggleClass()
Mar 31 jQuery
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
二次元帅气男生排行榜,只想悄悄收藏系列
2020/03/04 日漫
WampServer下安装多个版本的PHP、mysql、apache图文教程
2015/01/07 PHP
PHP连接MySQL数据的操作要点
2015/03/20 PHP
PHP5.0 TIDY_PARSE_FILE缓冲区溢出漏洞的解决方案
2018/10/14 PHP
js右键菜单效果代码
2007/07/21 Javascript
JavaScript-世界上误解最深的语言分析
2007/08/12 Javascript
比较详细的关于javascript 解析json的代码
2009/12/16 Javascript
new Date()问题在ie8下面的处理方法
2014/07/31 Javascript
JavaScript bold方法入门实例(把指定文字显示为粗体)
2014/10/17 Javascript
a标签的href与onclick事件的区别详解
2014/11/12 Javascript
jquery实现可关闭的倒计时广告特效代码
2015/09/02 Javascript
12个非常实用的JavaScript小技巧【推荐】
2016/05/18 Javascript
JS实现HTML表格排序功能
2016/08/05 Javascript
js中利用cookie实现记住密码功能
2020/08/20 Javascript
通过Ajax使用FormData对象无刷新上传文件方法
2016/12/08 Javascript
微信小程序switch开关选择器使用详解
2018/01/31 Javascript
关于微信小程序bug记录与解决方法
2018/08/15 Javascript
Python 3.6 性能测试框架Locust安装及使用方法(详解)
2017/10/11 Python
Python设计模式之MVC模式简单示例
2018/01/10 Python
Flask项目中实现短信验证码和邮箱验证码功能
2019/12/05 Python
python字符串替换re.sub()实例解析
2020/02/09 Python
tensorflow模型文件(ckpt)转pb文件的方法(不知道输出节点名)
2020/04/22 Python
详解CSS3中border-image的使用
2015/07/18 HTML / CSS
美国相机和电子产品零售商:Beach Camera
2020/11/26 全球购物
如何开发一个JQuery插件
2016/07/28 面试题
中专生求职自荐信范文
2013/12/22 职场文书
经济管理专业自荐信
2013/12/30 职场文书
军训考核自我鉴定
2014/02/13 职场文书
建筑专业毕业生自荐信
2014/05/25 职场文书
公司优秀员工获奖感言
2014/08/14 职场文书
2015年妇联工作总结范文
2015/04/22 职场文书
2015年医院护理部工作总结
2015/04/23 职场文书
2016年母亲节广告语
2016/01/28 职场文书
《初涉尘世》读后感3篇
2020/01/10 职场文书
《英雄联盟》2022日蚀、月蚀皮肤演示 黑潮亚索曝光
2022/04/13 其他游戏
原生JS实现分页
2022/04/19 Javascript