我们在使用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路由按需加载器和初始加载器的更多相关文章

  1. react-router 4.x 路由按需加载

    react-router 4 代码分割(按需加载) 官方文档  https://serverless-stack.com/chapters/code-splitting-in-create-react ...

  2. react16 路由按需加载、路由权限配置

    1. 路由按需加载: 不做按需加载,代码全部打包在bundle.js 文件里,首屏渲染很慢,项目文件较多,会出现1分钟加载的可能性. import React, { Component } from ...

  3. vue中路由按需加载的几种方式

    使用vue-cli构建项目后,我们会在Router文件夹下面的index.js里面引入相关的路由组件,如: import Hello from '@/components/Hello' import ...

  4. vue 动态路由按需加载的三种方式

    在Vue项目中,一般使用vue-cli构建项目后,我们会在Router文件夹下面的index.js里面引入相关的路由组件,如: import Hello from '@/components/Hell ...

  5. react路由按需加载方法

    使用router4之后以前的按需加载方法require.ensure 是不好使了. 所以我们改用react-loadable插件做按需加载. 第一步: yarn add react-loadable ...

  6. vue项目实现路由按需加载的3种方式

    vue异步组件技术 ==== 异步加载vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 .但是,这种情况下一个组件生成一个js文件 /* vue异步组件技术 */ { ...

  7. vue学习指南:第十二篇(详细) - Vue的 路由 第二篇 ( 路由按需加载(懒加载))

    各位朋友 因 最近工作繁忙,小编停更了一段时间,快过年了,小编祝愿 大家 事业有成 学业有成 快乐健康 2020开心过好每一天.从今天开始 我会抽时间把 Vue 的知识点补充完整,以及后期会带给大家更 ...

  8. react 实现路由按需加载

    import() 方法: async.js 文件内容: import React from 'react'; // import "babel-polyfill"; //compo ...

  9. Google官方网络框架-Volley的使用解析Json以及加载网络图片方法

    Google官方网络框架-Volley的使用解析Json以及加载网络图片方法 Volley是什么? Google I/O 大会上,Google 推出 Volley的一个网络框架 Volley适合什么场 ...

随机推荐

  1. 机器学习:DeepDreaming with TensorFlow (二)

    在前面一篇博客里,我们介绍了利用TensorFlow 和训练好的 Googlenet 来生成简单的单一通道的pattern,接下来,我们要进一步生成更为有趣的一些pattern,之前的简单的patte ...

  2. Qt翻译---Thread Support in Qt

    Thread Support in Qt QT提供线程支持在平台独立的线程类.一个安全线程的传递事件的方式,一个信号槽的链接在线程之中.这使得开发多线程容易.多线程程序也是一个有用的范例为不冻结用户界 ...

  3. [转]TensorFlow如何进行时序预测

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库.节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组 ...

  4. CefSharp For WPF隐藏滚动条

    效果:开始的时候会显示几秒,之后就不会再显示了 <!--浏览器--> <cefSharpWPF:ChromiumWebBrowser Name="webBrowser&qu ...

  5. Win10《芒果TV》更新v3.8.30流星版:优化稳定性、升级无边框播放体验

    随着暑假到来,大波王牌综艺和青春电视剧热浪来袭,Win10版<芒果TV>全平台同步更新流星版v3.8.30,进一步提升稳定性,巩固播放体验,升级剧场模式和画中画无边框体验,我们在芒果等你. ...

  6. Android开发参考资料

    Android入门第九篇之AlertDialog: http://blog.csdn.net/hellogv/article/details/5955959 Android的AlertDialog详解 ...

  7. List<T>多字段排序的一个通用类

    本文中的方法旨在解决通用的问题,非常注重效率的地方,还应该针对具体的类去写排序方法. 废话不多说,直接上代码 具体使用场景: 要排序的类 1 public class bb 2 { 3 public ...

  8. 用vs2010编译好的ICU库

    1.ICU库的官网网址为http://site.icu-project.org/ 2.ICU(International Components for Unicode)是一个国际化的字符编码和转化的库 ...

  9. c#基于Tablet pc实现的手写输入

    需要安装Tablet pc,win7的话 直接在控制面板>程序和应用>添加组建里面勾选上添加 然后就是下面的程序了,看代码 设计文件 namespace 手写识别 { partial cl ...

  10. QT在linux环境下读取和设置系统时间(通过system来直接调用Linux命令,注意权限问题)

    QT在Linux环境下读取和设置系统时间 本文博客链接:http://blog.csdn.NET/jdh99,作者:jdh,转载请注明. 环境: 主机:Fedora12 开发软件:QT 读取系统时间 ...