一般我们在大部分node框架中都见过,在既定的文件夹内只要新增了文件或者文件夹,路由会自动生成,无需人工引入。
这种做法就是我们常说的约定优于配置的一种实现。
假定文件夹结构如下,且内部均实现了router.get(‘/‘) – src —-routes ——–index.ts ——–user ————info.ts ————modify.ts
那么理论上就应该生成如下路由
开发思路
将路由的初始化等工作交给工具类,工具类初始化返回根路由实例,app可以继续操作路由。
指定特定的路由文件夹,由工具类进行扫描,生成路由返回
功能点
工具类单例模式,只需要一个实例即可
初始化配置与koa-router初始化配置一致
核心:递归读取路由文件夹,生成绝对路径 3.1 读取模块文件 3.2 生成路由 3.3 返回路由
功能实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 import path from "path" ;import fs from "fs" ;import Router , { IRouterOptions } from "koa-router" ;class RoutesLoader { private options : IRouterOptions = {} as IRouterOptions ; private static instance : RoutesLoader | null = null ; static getInstance ( ) { if (!this .instance ) { this .instance = new RoutesLoader (); } return this .instance ; } async init (options?: IRouterOptions ) { if (options) { this .options = options; } const routeFiles = this .getFiles (); return await this .loadRoutesWrapper (routeFiles); } isRouter (data : any ): data is Router { return data instanceof Router ; } setRootRouter ( ) { const rootRouer = new Router (this .options ); return rootRouer; } getFiles ( ) { function _getFiles (dir: string , filepath: string ): string [] { let retArr : string [] = []; const fullPath = path.resolve (dir, filepath); const files = fs.readdirSync (fullPath); for (const file of files) { const stat = fs.statSync (path.resolve (fullPath, file)); if (stat.isDirectory ()) { retArr = [...retArr, ..._getFiles (fullPath, file)]; } else if (stat.isFile ()) { retArr.push (path.resolve (fullPath, file)); } } return retArr; } return _getFiles (process.cwd (), "src/routes" ); } async loadRoutesWrapper (allFullFilePath: string [] ) { const rootRouer = this .setRootRouter (); for (const fullPath of allFullFilePath) { const module = await import (fullPath); if (this .isRouter (module .default )) { rootRouer.use (module .default .routes (), module .default .allowedMethods ()); } } return rootRouer; } } export default RoutesLoader .getInstance ();
demo 跳转github打开clone demo运行