【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适合什么场 ...
随机推荐
- xmarin live player 连接 IOS以及安卓实现实时效果查看
原文:xmarin live player 连接 IOS以及安卓实现实时效果查看 在之前有介绍过xamarin 单独IOS项目开发的运行环境搭建,但是这段时间我看到了xmarin forms 3.0 ...
- WPF 四种尺寸单位
原文:WPF 四种尺寸单位 像素 px 默认单位可以省略 厘米cm 英寸 in 点 pt 1in = 96px 1cm=96/2.42px 1pt=96/72px
- WPF元素绑定
原文:WPF元素绑定 数据绑定简介:数据绑定是一种关系,该关系告诉WPF从源对象提取一些信息,并用这些信息设置目标对象的属性.目标属性是依赖项属性.源对象可以是任何内容,从另一个WPF元素乃至ADO. ...
- WPF 集合分组排序
<Window x:Class="ViewExam.MainWindow" xmlns="http://schemas.microsoft.com/w ...
- TestDisk 数据恢复 重建分区表恢复文件-恢复diskpart clean
source:http://www.cgsecurity.org/wiki/TestDisk_CN TestDisk 是一款开源软件,受GNU General Public License (GPL ...
- 人像美妆---妆容迁移算法研究(Makeup transfer)
原文:人像美妆---妆容迁移算法研究(Makeup transfer) 对于人像美妆算法,现在的美妆相机.玩美彩妆之类的app已经做的比较成熟了,但是具体算法,基本网络上是杳无可查,今天本人介绍一种自 ...
- android 录屏
录屏,google了一下,记录下来,以免FQ android 4.4 录屏可通过adb:adb shell screenrecord /sdcard/video.mp4 (未测试) android 5 ...
- AngularJS的简单使用(入门级)
AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前端JS框架,已经被用于Google的多款产品当中. AngularJS有着诸多特性,最为 ...
- 解释下Func<T, bool> exp
比如 interface IRepository<T> where T:class { IEnumerable<T> FindAll(Func<T, bool> e ...
- Windows完成端口与猪肉佬
首先应该说明的是,我也是第一次使用完成端口.虽然以前偶尔在网上看到完成端口的文章和代码,但真正自己动手写还是第一次,不过我这个人有个特点就是大胆,例如没有写那个界面编程系列前,其实我甚至不知道原来一个 ...