在 Express.js 中,路由是非常重要的概念。通过路由,我们可以将不同的请求映射到不同的处理函数,从而实现网站的各种功能。常见的表现形式即为一个个静态路由,例如 /home
, /user
, /api
, /news
等,这些路由的处理逻辑都是直接在代码中定义好的。但是随着网站的功能越来越多,很可能会产生大量的路由,这时候静态路由已经无法满足需求,必须采用动态路由的方式。
动态路由是指路由的配置是在运行时动态生成的,根据某些规则去依次匹配请求,并调用对应的处理程序。这样可以节省很多代码,让路由的配置更加灵活。如何在 Express.js 中实现动态加载路由呢?接下来,我们将详细讲解其原理和实现方式。
原理
动态路由的实现原理和静态路由是有所不同的。静态路由常常是将所有路由都预先注册到 Express.js 中,然后在请求到来时,通过正则表达式匹配来找到相应的路由处理程序。这样做的缺点是,如果路由太多,会使应用的启动速度变慢,同时也会占用很多内存。
而动态路由则不同,其注册流程是在应用启动时,扫描指定目录或数据库等数据源,并根据扫描结果动态注册路由。这样做的优点是路由项只载入需要的,对内存不会造成太大压力,而且可以更灵活方便的管理路由。
实现
接下来我们开始动手实现动态路由。为了方便起见,我们设定一下我们的动态路由规则是: 所有路由处理程序都写在 ./routes
目录中,每个文件都是一个路由处理程序的集合,并且每一个文件的命名规则必须是 [路由前缀]-[请求方法].js
,例如 user-get.js
,表示处理的是 /user
路由的 GET 请求。
第一步,我们需要启动应用,并开始扫描 ./routes
目录中的路由处理程序文件。这里我们使用 fs.readdirSync
函数来遍历目录下的文件,并返回它们的文件名:
const fs = require('fs'); const { join } = require('path'); const ROUTES_DIR = join(__dirname, 'routes'); // 路由处理程序所在的目录 const routes = fs.readdirSync(ROUTES_DIR);
第二步,我们需要通过 express.Router
构造函数,来创建一个路由器实例。这个路由器实例是负责将所有的动态路由处理程序融合在一起的核心。同时,我们在路由器实例上定义了一个自定义方法 applyRoutes
,用来遍历所有的路由处理程序,并将它们注册到应用中:
// javascriptcn.com 代码示例 const express = require('express'); const router = express.Router(); router.applyRoutes = function() { routes.forEach(function(file) { if (file.match(/^\./)) return; // 忽略掉点文件 const prefix = file.split('-')[0]; // 路由前缀 const method = file.split('-')[1].split('.')[0].toUpperCase(); // 请求方法 const routeHandler = require(join(ROUTES_DIR, file)); // 路由处理程序 router[method.toLowerCase()](`/${prefix}`, routeHandler); }); }
第三步,我们将上述实现进行封装,创建出一个 Express.js 的中间件函数,以便于在应用启动时调用:
function dynamicRoutes() { ROUTER.applyRoutes(); }
第四步(可选),如果你想提高性能,可以将路由前缀作为目录名,并将处理程序文件放置在里面,这样扫描目录的时候会更快,例如:
// javascriptcn.com 代码示例 routes/ ├── api │ ├── get.js │ └── post.js ├── home │ └── get.js └── user ├── delete.js ├── get.js ├── post.js └── put.js
上面的实现流程最终会使动态路由被注册到 Express.js 应用程序中,这样我们就可以通过请求不同的路由路径,来执行相应的动态路由了。
示例代码
// javascriptcn.com 代码示例 const express = require('express'); const fs = require('fs'); const { join } = require('path'); const ROUTES_DIR = join(__dirname, 'routes'); // 路由处理程序所在的目录 const app = express(); app.use(dynamicRoutes()); app.listen(3000, () => { console.log('Server is listening on port 3000'); }); function dynamicRoutes() { const ROUTER = express.Router(); ROUTER.applyRoutes = function() { const routes = fs.readdirSync(ROUTES_DIR); routes.forEach(function(file) { if (file.match(/^\./)) return; // 忽略掉点文件 const prefix = file.split('-')[0]; // 路由前缀 const method = file.split('-')[1].split('.')[0].toUpperCase(); // 请求方法 const routeHandler = require(join(ROUTES_DIR, file)); // 路由处理程序 ROUTER[method.toLowerCase()](`/${prefix}`, routeHandler); }); } return ROUTER; }
总结
动态路由是一种非常强大的路由配置方法,它使得我们可以将路由的配置与实现分离开来,从而使得应用的配置更加灵活,同时也减轻了代码的负担。通过上述的实现方式,我们可以轻松地在 Express.js 中实现动态路由,相信这对于你的工作会有很大的帮助。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6534bcd67d4982a6eb9dafaf