【koa2基础框架封装】基于Proxy路由按需加载器和初始加载器
我们在使用koa2做路由拦截后一般都习惯于直接将查找对应处理函数的过程映射到项目的文件夹目录,如:
router.get('/test', app.controller.index.test);
app.controller.index.test 其实就是对应的处理函数,也就是 (ctx, next) => { },我们习惯于将app.controller.index.test映射到根目录下的 /controller/index/test.js ;或映射至 /controller/index.js,此时index.js的导出为一个对象,存在一个test的函数, 可以是:
{
test: async (ctx, next) => { }
}
实现这种类似的目录映射,一般有两种实现方式:
(1)初次controller加载器
(2)拦截时的按需controller加载器
两种方式各有利弊:
一、初次controller加载器
服务启动时依次遍历整个controller目录下的文件夹,并通过require动态绑定至对应的对象上。比较适合小型项目。
优点:只需要在服务启动时执行依次,后续无需再根据目录查找。
缺点:当项目文件量足够大时,重启服务的时间会变长,在宕机重启时,线上体验会有影响。
核心代码如下:
const path = require("path");
const fs = require('fs');
module.exports = function (opts) {
let {app,rules = []} = opts;
// 如果参数缺少实例 app,则抛出错误
if (!app) {
throw new Error("the app params is necessary!");
}
// 提取出 app 实例对象中的属性名
const appKeys = Object.keys(app);
rules.forEach((item) => {
let {folder,name} = item;
// 如果 app 实例中已经存在了传入过来的属性名,则抛出错误
if (appKeys.includes(name)) {
throw new Error(`the name of ${name} already exists on app!`);
}
let content = {};
//读取指定文件夹下(dir)的所有文件并遍历
fs.readdirSync(folder).forEach(filename => {
let extname = path.extname(filename); // 取出文件的后缀
if (extname === '.js') { // 只处理js文件
let name = path.basename(filename, extname); // 将文件名中去掉后缀
//读取文件中的内容并赋值绑定
content[name] = require(path.join(folder, filename));
}
});
app[name] = content;
})
app.use(async (ctx, next) => {
rules.forEach((item, index) => {
let {name} = item;
if (Object.keys(ctx).indexOf(name) !== -1) {
throw new Error(`the name of ${name} already exists on ctx!`)
} else {
ctx[name] = app[name];
}
})
await next();
})
}
// 调用
miFileMap({
app,
rules: [{ //指定controller文件夹下的js文件,挂载在app.controller属性
folder: path.join(__dirname, '../controller'),
name: 'controller'
}
]
});
二、拦截时的按需controller加载器
在路由拦截时,根据当前路由寻找对应的文件模块,比较适合大型项目。
优点: 重启时间快,线上部署宕机重启时影响较小。
缺点: 每次的路由拦截时间后的寻找controller的时间会微微增长
在实现按需加载的时候,刚开始是面向过程的写法,会出现多次访问同一路由受影响的情况,所以以面向对象方式实现。
核心代码如下:
const path = require('path');
const fs = require('fs');
class DirProxy {
constructor (root) {
this.dir = [root];
}
static getFile (baseDir) {
const baseFile = baseDir + '.js';
let targetDir = null,
targetFile = null;
try {
targetDir = fs.statSync(baseDir);
} catch (err) {}
try {
targetFile = fs.statSync(baseFile);
} catch (err) {}
// console.log(baseDir, baseFile)
if (targetDir || targetFile) {
if (targetDir && targetDir.isDirectory()) {
return 'dir'
}
if (targetFile && targetFile.isFile()) {
return 'file'
}
return false;
} else {
return false;
}
}
init () {
let _this = this;
let handler = {
get (target, key, receiver) {
console.log('dirproxy')
console.log(key)
// key可能会是Symbol(nodejs.util.inspect.custom)
if (key && Object.prototype.toString.call(key) === '[object String]') {
_this.dir.push(key)
}
// c:/FE/nodeFile/node_base_learn/ 为项目根目录
let baseDir = path.relative(__dirname, `c:/FE/nodeFile/node_base_learn/${_this.dir.join('/')}`);
let ctrPath = path.resolve(__dirname, baseDir)
let targetCtr = DirProxy.getFile(ctrPath);
if (targetCtr == 'dir') {
return new Proxy({path: _this.dir}, handler);
} else {
// 根据commonjs的模块解析规则可直接引入目录或js文件
return require(ctrPath)
}
},
set (target, key, value, receiver) {
return false;
},
construct: function(target, args) {
return false;
}
}
return new Proxy({path: _this.dir}, handler)
}
}
module.exports = DirProxy
现在只是完成了get,set可根据自己需要定制。所有set直接返回false,即只读,也是可以的。
//调用方式
app.controller = new DirProxy('controller').init(); // 调用之后,便会以链式的方式逐级目录寻找js文件
app.controller.user.login
站在公司或项目长期发展的角度考虑问题的话,按需加载仍是相对稳妥的办法
koa2 定制开源框架github:https://github.com/pomelott/koa2_custom_optimize
框架持续更新中,喜欢请赐星。。。
【koa2基础框架封装】基于Proxy路由按需加载器和初始加载器的更多相关文章
- react-router 4.x 路由按需加载
react-router 4 代码分割(按需加载) 官方文档 https://serverless-stack.com/chapters/code-splitting-in-create-react ...
- react16 路由按需加载、路由权限配置
1. 路由按需加载: 不做按需加载,代码全部打包在bundle.js 文件里,首屏渲染很慢,项目文件较多,会出现1分钟加载的可能性. import React, { Component } from ...
- vue中路由按需加载的几种方式
使用vue-cli构建项目后,我们会在Router文件夹下面的index.js里面引入相关的路由组件,如: import Hello from '@/components/Hello' import ...
- vue 动态路由按需加载的三种方式
在Vue项目中,一般使用vue-cli构建项目后,我们会在Router文件夹下面的index.js里面引入相关的路由组件,如: import Hello from '@/components/Hell ...
- react路由按需加载方法
使用router4之后以前的按需加载方法require.ensure 是不好使了. 所以我们改用react-loadable插件做按需加载. 第一步: yarn add react-loadable ...
- vue项目实现路由按需加载的3种方式
vue异步组件技术 ==== 异步加载vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 .但是,这种情况下一个组件生成一个js文件 /* vue异步组件技术 */ { ...
- vue学习指南:第十二篇(详细) - Vue的 路由 第二篇 ( 路由按需加载(懒加载))
各位朋友 因 最近工作繁忙,小编停更了一段时间,快过年了,小编祝愿 大家 事业有成 学业有成 快乐健康 2020开心过好每一天.从今天开始 我会抽时间把 Vue 的知识点补充完整,以及后期会带给大家更 ...
- react 实现路由按需加载
import() 方法: async.js 文件内容: import React from 'react'; // import "babel-polyfill"; //compo ...
- Google官方网络框架-Volley的使用解析Json以及加载网络图片方法
Google官方网络框架-Volley的使用解析Json以及加载网络图片方法 Volley是什么? Google I/O 大会上,Google 推出 Volley的一个网络框架 Volley适合什么场 ...
随机推荐
- WPF 实现波浪浮动效果
原文:WPF 实现波浪浮动效果 目标:实现界面图标Load时,整体图标出现上下波浪浮动效果,如下图: 前台代码: <Windowxmlns="http://schemas.micros ...
- AABB边框、OBB边框、通过比较球包围
1) AABB 包围盒: AABB 包围盒是与坐标轴对齐的包围盒, 简单性好, 紧密性较差(尤其对斜对角方向放置的瘦长形对象, 採用AABB, 将留下非常大的边角空隙, 导致大量不是必需的包围盒相交測 ...
- Android 百度地图 SDK v3.0.0 (四) 离线地图功能介绍
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/37758097 一直认为地图应用支持离线地图非常重要啊.我等移动2G屌丝,流量不易 ...
- 关于 IIS 上运行 ASP.NET Core 站点的“HTTP 错误 500.19”错误
昨天回答了博问中的一个问题 —— “HTTP 错误 500.19 - Internal Server Error dotnetcore”,今天在这篇随笔中时候事后诸葛亮地小结一下. 服务器是 Wind ...
- C#热敏打印图片 串口打印图片
原文:C#热敏打印图片 串口打印图片 如图,一步一步慢慢调出来的 //串口通信类 public System.IO.Ports.SerialPort serialPort = null; serial ...
- .Net Core 中使用PetaPoco ,T4生成模版
话不多说,直接上源码. 1.引用NuGet 2.添加T4 <#@ template debug="true" hostspecific="false" l ...
- 零元学Expression Blend 4 - Chapter 37 看如何使用Clip修出想要的完美曲线(上)
原文:零元学Expression Blend 4 - Chapter 37 看如何使用Clip修出想要的完美曲线(上) 几何外部的 UIElement 会在呈现的配置中以视觉化方式裁剪. 几何不一定要 ...
- 零元学Expression Blend 4 - Chapter 32 简单轻松的学会如何使用Visual States(上)
原文:零元学Expression Blend 4 - Chapter 32 简单轻松的学会如何使用Visual States(上) Visual State Manager中文翻译为视觉状态管理器,这 ...
- 【Windows10 IoT开发系列】API 移植工具
原文:[Windows10 IoT开发系列]API 移植工具 Windows 10 IoT Core 中是否提供你的当前 Win32 应用程序或库所依赖的 API? 如果不提供,是否存在可使用的等效 ...
- 简单的Windows Webcam应用:Barcode Reader
原文:简单的Windows Webcam应用:Barcode Reader 在Windows上用WinForm创建一个Webcam应用需要用到DirectShow.DirectShow没有提供C#的接 ...