Koa在实际的业务场景中,路由如何做分割?【文末留言送书】

大家好,我是若川。文末留言送书,具体规则文末说明。另外为了鼓励大家多写源码共读笔记,我会在写了5次及以上笔记的作者群里也抽奖送这本书。以后也会有更多福利倾斜。

3ce37dcd64660c068fedf25387bf3e86.png

导读:Koa是一个Node框架,在Node开源社区中,Koa的使用范围非常广,掌握Koa的使用方法,就能轻松应对业界的一些BFF框架。本文介绍Koa在实际的业务场景中,路由如何做分割。

a45c84c43a2d481224b497b263be28d1.png

作者:刘江虹

来源:华章计算机(hzbook_jsj)

在实际的复杂业务场景中,简单的路由堆砌会使得路由文件越来越大,随着后续的项目不断迭代,开发人员的不断更替,如果所有的路由都写在一个文件里,会使得路由模块变得越来越难维护。

那么,Koa的项目要如何去解决路由难维护的问题呢?对于这个问题,由抖音电商前端架构师撰写的《Koa开发:入门、进阶与实战》给出了很好的解决方案,下面让我们结合这本书的内容来详细看一看Koa中路由的使用技巧。

在介绍路由分割以及文件路由之前,我们回忆一下koa-router这个中间件的使用。假如需要两个路由,一个是获取货物信息,一个是获取用户信息,那用koa-router实现的代码应该是这样的:

const Koa = require('koa')const app = new Koa()const Router = require('koa-router')const router = new Router()router.get('/goods/getInfo', async ( ctx ) => {ctx.body = 'this is koa book.'})router.get('/user/getInfo', async ( ctx ) => {ctx.body = 'my name is liujianghong.'})app.use(router.routes())app.listen(4000, () => {console.log('server is running, port is 4000')})

这样的写法相信读者应该已经掌握了,但这样写其实有个弊端,如果在一个实际的项目中,Node.js层的接口可能会很多,所有的路由都放在一个文件里,最终会变得越来越难维护,那实战中我们应该如何维护好路由的编写呢?本节将阐述两种方案。

1、路由分割

所谓路由分割,就是把所有路由按照类别划分,分别维护在不同的文件里。在实际的项目中,通常情况下,一个项目是由多人开发维护的,比如张三只维护货物相关的路由,李四只维护用户相关的路由,如果让两人在一个文件里维护,那随着项目越来越大,接口越来越多,难免会出现不好维护的情况。所以,路由分割就一定程度上解决了这样的问题,让路由易迭代、易维护。

本文提到的实例中有两个类型的路由,一个是货物的,一个是用户的,那么接下来,我们就对这两类路由进行分割。首先,按照类型可以把不同的路由写在不同的文件里,货物的路由文件代码如下:

// routers/goods.jsconst Router = require('koa-router')const router = new Router()// 设置路由前缀router.prefix('/goods')router.get('/getInfo', (ctx, next)=>{ctx.body = "this is koa book."})module.exports = router

用户的路由文件代码如下:

// routers/user.jsconst Router = require('koa-router')const router = new Router()router.prefix('/user')router.get('/getInfo', (ctx, next)=>{ctx.body = "my name is liujianghong."})module.exports = router

每个路由文件里面都使用了一个路由前缀的设置,这样方便分类。每个文件封装了不同类型的路由,接下来要做的就是把这些路由进行整合。Koa源码中有一个非常重要的实现是中间件的合并,其中就使用了koa-compose包,读者可以返回《Koa开发:入门、进阶与实战》一书的第3章复习一下。路由的合并也会用到koa-compose来进行实现,代码如下:

// routers/index.jsconst compose = require('koa-compose')const glob = require('glob')const { resolve } = require('path')registerRouter = () => {let routers = [];// 递归式获取当前文件夹下所有的js文件glob.sync(resolve(__dirname, './', '**/*.js'))// 排除index.js文件,因为这个文件不是具体的路由文件.filter(value => (value.indexOf('index.js') === -1)).forEach(router => {routers.push(require(router).routes())routers.push(require(router).allowedMethods())})return compose(routers)}module.exports = registerRouter

这里可以使用koa-compose来对koa-router进行整合,是因为koa-router里面的routers方法和allowedMethods方法和我们平时用的中间件里面的回调是一样的,读者如果感兴趣的话,可以看一下koa-router的源码。最后实现一个简单的server,即把整合后的路由引进来,代码如下:

// app.jsconst Koa = require('koa')const registerRouter  = require('./routers')const app = new Koa()app.use(registerRouter())app.listen(4000, () => {console.log('server is running, port is 4000')})

运行app.js,我们在浏览器访问http://127.0.0.1:4000/goods/getInfo,效果如图1所示。

b4cd201cd449567eef1a6a91dbe50e10.png 图1 访问货物路由运行结果

访问http://127.0.0.1:4000/user/getInfo,效果如图2所示。 

1efe3c9f39bb3a185b32defe0a256a18.png

图2 访问用户路由运行结果


2、文件路由

根据文件路径来匹配路由,也是实际的项目可能采取的一种方式,我们先了解一下什么是文件路由,比如,现在有这样一个项目,组织结构如图3所示。

d19150c17a3e651bdd0a76ff68ff1413.png 图3 文件路由的项目结构

actions目录下的内容就是匹配路由的,比如前端有一个GET请求http://127.0.0.1:4000/goods/getInfo,那么最终会匹配到actions目录下goods/getInfo.js文件,最终会执行getInfo.js里面的逻辑。这么设计有以下几点优势:

● 依据项目中文件目录就能了解本项目都有哪些路由,不用查看路由文件,非常方便。

● 用文件路径来组织路由,对用户非常友好,便于开发。

接下来我们详细分析这种文件路由该如何实现。总共有两个步骤:第一步,定义goods/getInfo.js和user/getInfo.js两个文件内容,主要是定义一些属性,包括请求的方法类型(GET、POST等)、执行的回调;第二步,把请求的path映射到对应的文件路径上,当请求过来后,能够执行对应的文件内容。接下来看代码如何实现。

1)定义两个文件内容

actions/goods/getInfo.js文件的定义代码如下:

// actions/goods/getInfo.jsmodule.exports = {method: 'GET',  handler: (ctx) => {ctx.body = "this is koa book."}    }

actions/user/getInfo.js文件的定义代码如下:

// actions/user/getInfo.js module.exports = {   method: 'GET',   handler: (ctx) => {     ctx.body = "my name is liujianghong."   }     }

两个文件都定义了两个属性,一个是method,一个是handler。method指的是请求的类型,这里method的配置主要是为了映射到唯一请求,比如请求路径都是/goods/getInfo,那方法类型既可以是GET请求,也可以POST请求,两个请求是不一样的。hander方法就是一个回调方法,用来处理相应的业务逻辑。

2)请求的path映射到对应的文件

首先请求的path可通过context对象来获取,比较方便,主要问题是文件路径如何处理。其实我们可以通过glob这个包来获取所有的文件,然后对路径再做相应的处理即可,代码如下:

const glob = require('glob')const path = require('path')const Koa = require('koa')const app = new Koa()// actions的绝对路径const basePath = path.resolve(__dirname, './actions')// 获取actions目录下所有的js文件,并返回其绝对路径const filesList = glob.sync(path.resolve(__dirname, './actions', '**/*.js'))// 文件路由映射表let routerMap = {}filesList.forEach(item => {// 解构的方式获取,当前文件导出对象中的method属性和handler属性const { method, handler } = require(item)// 获取和actions目录的相对路径,例如:goods/getInfo.jsconst relative = path.relative(basePath, item)// 获取文件后缀.jsconst extname = path.extname(item)// 剔除后缀.js,并在前面加一个"/",例如:/goods/getInfoconst fileRouter = '/' + relative.split(extname)[0]// 连接method,形成一个唯一请求,例如: _GET_/goods/getInfoconst key = '_' + method + '_' + fileRouter// 保存在路由表里routerMap[key] = handler})app.use(async (ctx, next) => {const { path, method } = ctx// 构建和文件路由匹配的形式:_GET_路由const key = '_' + method + '_' + path// 如果匹配到,就执行对应到handlerif (routerMap[key]) {routerMap[key](ctx)} else {ctx.body = 'no this router'}})app.listen(4000, () => {console.log('server is running, port is 4000')})

文件路由书写起来比较优雅,并且可以做到高度可配置,这样对每个请求可以实行个性化定制,我们在Koa实战中也会使用这种方式来做路由,到时候详细讲述企业级别的BFF架构中文件路由该如何设计。

无论是通过中间件的路由分割还是通过文件的路由分割,都在一定程度上能够优化路由的组织方式,方便后续的需求迭代。如果您想要了解更多有关Koa的高级应用,如用户鉴权机制、数据存储、进程管理等,推荐您详细阅读刘江虹老师的新作《Koa开发:入门、进阶与实战》。

作者介绍:刘江虹,字节跳动抖音电商前端架构师,目前主要负责业务架构中工程化等相关方向,拥有多年前端架构工作经验。独立开发过一款可对标Egg的BFF企业级框架,支撑公司线上服务超1000个,全栈前端技术专家,具有丰富的Node实战经验。著有畅销书《React.js实战》。

087db974613317529c80ac2a0b2ff792.png


抽奖规则:在留言区留言为什么想要这本书,随机抽取「2位」理由充分 && 关注比较久 && 留言互动相对多的小伙伴。包邮送出本书。

另外为了鼓励大家多写源码共读笔记,我会在写了5次及以上笔记的作者群里也抽奖送这本书。以后也会有更多福利倾斜。

开奖时间4月18日(周一)晚8点。中奖者在开奖后1天内与我取得联系,否则视为放弃。我会在微信留言区回复中奖人。

中奖者开奖前必须是我的微信好友,且需是前端。羊毛党绕路。

总之最终解释权归我。

记得扫码加我微信 ruochuan12 , 参加源码共读。

600e42f49ccae7499b0308aa49106710.png

02bcea82e55a1bc245b4a192f57ce67a.gif

点击阅读全文购买

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/274740.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式_设计

设计模式Thanks for my colleague WanChing‘s help to prepare this sharing article. E-Commerce app collects plentiful products from various brands. Each brand has its brand signature colors and public image. This article introduces how we made a single page …

动态切换css

方法一&#xff1a;给link一个id&#xff0c;直接获取该DOM操作href <link rel"stylesheet" id"stylelink" type"text/css"/> <a href"#" οnclickjavascript:document.getElementById("stylelink").href "…

使用 GTD 优化自己的工作和生活

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

模仿不再受宠若惊

If you haven’t heard of the Jio-Zoom plagiarism clash, you’re probably living under a rock (which may not be a bad idea given the state of the world right now). The turf war between Jio Meet and Zoom began when the Indian telecom giant ripped off the Chi…

一个计算机爱好者的不完整回忆(二十八)关于计算机书籍

我只在大学阶段在图书馆看了很多计算机方面的书&#xff0c;无论已经老得都残破了还是最新出版的。前两天又看到论坛中有关于计算机书籍特别是国内人士编写或翻译的计算机书籍的评论的文章&#xff0c;谭浩强老先生又毫无悬念的被牵连了进来。也发表一下自己的一些观点吧。   …

Vue2剥丝抽茧-响应式系统 系列

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

word文本样式代码样式_使用文本样式表达创建真相来源

word文本样式代码样式As of After Effects 17.0, you can use expressions to edit text styles in After Effects. Here’s why this would transform your workflow:从After Effects 17.0开始&#xff0c;您可以使用表达式在After Effects中编辑文本样式。 这就是这将改变您的…

mvn备忘

创建web工程 mvn archetype:generate -DgroupIdcom.malangmedia -DartifactIdautoDeployToJetty -DarchetypeArtifactIdmaven-archetype-webapp -Dversion1.0 添加jetty插件 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.or…

前端框架源码解读之Vite

前端工具链十年盘点&#xff1a;https://mp.weixin.qq.com/s/FBxVpcdVobgJ9rGxRC2zfgWebpack、Rollup 、Esbuild、Vite ?webpack: 基于 JavaScript 开发的前端打包构建框架&#xff0c;通过依赖收集&#xff0c;模块解析&#xff0c;生成 chunk&#xff0c;最终输出生成的打包…

hp-ux_UX中的格式塔-或-为什么设计师如此讨厌间距

hp-uxI’ve been lucky so far in my design career to have worked with engineers that seem genuinely interested in learning about design. Perhaps, as mentioned in the title, it’s more about them trying to figure out why it matters so much to us that there i…

很多人都不知道,其实博客园给我们博客开了二级域名

如题。一直都在邮件签名里写自己的博客地址为&#xff1a; http://www.cnblogs.com/datacool&#xff1b;直到有天突然发现使用&#xff1a;http://datacool.cnblogs.com也可以访问。不知道的赶紧测试&#xff0c;后者明显要酷很多啊。该不是我是最后一个知道的吧&#xff0c;知…

JavaScript 数组新增 4 个非破坏性方法!

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…

自行车改装电动车怎么样_电动车听起来应该是什么样?

自行车改装电动车怎么样The sound of an all-electric car accelerating doesn’t have to sound like a standard combustion engine, It could sound like anything.全电动汽车加速的声音不必听起来像是标准的内燃机&#xff0c;它可以听起来像任何东西。 These were the wor…

C++中的三种继承public,protected,private(转)

三种访问权限 public:可以被任意实体访问 protected:只允许子类及本类的成员函数访问 private:只允许本类的成员函数访问 三种继承方式 public 继承 protect 继承 private 继承 组合结果 基类中 继承方式 子类中 public &#xff06; public继承 > public public &#xff0…

如何碎片化时间学前端,了解前沿趋势

我很开心在前端行业认识了一批优秀且乐于分享的朋友&#xff0c;他们的技术分享与职业观点让我获益良多&#xff0c;推荐给大家一起关注。程序员成长指北Node.js 前端工程化 低代码考拉小姐姐&#xff0c;一个有趣且乐于分享的人&#xff01;目前就职于某知名外企&#xff0c;负…

谷歌pay破解_Google Pay缺少Google闻名的一件事-UX案例研究

谷歌pay破解Disclaimer: The views expressed in the blog post is purely based on personal experience. It was not influenced by any external factor.When Google launched Tez (now Google Pay) in India during 2017, their primary goal was to design a simple payme…

进阶高级前端,这位大前端架构师一定不能错过

今天给大家介绍一位好朋友&#xff1a;这波能反杀&#xff1a;一位拥有十年工作经验&#xff0c;对学习方法有独到理解的资深大前端架构师。一、博客早在 2017 年初&#xff0c;波神在简书平台以《前端基础进阶》为名&#xff0c;更新了一系列优质文章&#xff0c;获得大量认可…

memcached应用策略(转)

memcached应用策略&#xff08;转&#xff09;(2012-04-05 11:10:02) 转载▼标签&#xff1a; memcached 应用策略 it分类&#xff1a; linux_c memcached应用策略memcached 主要的作用是为减轻大访问量对数据库的冲击&#xff0c;所以一般的逻辑是首先从memcached中读取数据&a…

突然讨厌做前端,讨厌代码_为什么用户讨厌重新设计

突然讨厌做前端,讨厌代码重点 (Top highlight)The core of design thinking is to only design something that will bring value and fill the gap in consumer needs. Right? Why else would one design something that no one asked for? While that may be true to some …

那些年我面过的「六年经验」的初级工程师

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以 点此加我微信ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外…