点击上方👆蓝色“Agilean”,发现更多精彩。
前情提要
在本系列上一篇文章《全文干货:打破前后端数据传递鸿沟,高效联调秘笈》中我们分享了使用Zod这一运行时类型校验库来对后端服务响应结果进行验证达到增加项目质量的方式。
这次,我们将继续分享利用这一种方式所附加的另一项能力:Mock服务。
什么是Mock服务?
mock服务是一种模拟或虚拟的服务器,用于模拟真实的API行为和响应,而无需实际访问后端服务器。这个概念在前后端项目分离,特别是开发人员分离的情况下经常被使用,有助于前后端并行开发,减少阻塞时间,提升交付时效。
常见的做法包括但不限于以下两种:
1.手动创建一份静态的响应数据声明成常量或是文件,再由程序读取;
2.资源丰富的团队可能还会自己架设一台真实服务器来提供mock服务,这类mock服务的响应结果通常会根据一定的规格文件产出随机的数据。
以上这两种方式,笔者认为均有各自的不足之处:
针对第一种,静态数据的方式体现不出数据的动态与完整性。举个例子,一份静态数据可能无法体现出某一个枚举字段的多值情况,也可能没有写出没有返回的可能字段。
针对第二种,架设公共mock服务有成本问题,以及对数据规格的描述可能会存在三方(前端、后端、mock服务)同步的问题。
综合考虑了不同应用形式的优劣势,知微前端团队开辟了另一条路:集成在前端项目中的 mock API。弥补了静态数据的不足,并且成本很小,能够尽量减少数据规格多方同步的问题。
应用逻辑:利用Schema产出Mock数据
在TypeScript中,我们可以使用 type 定义一个数据的规格,即这份数据包含了什么东西、长什么样子,为了便于大家阅读,下文统一将此称作 Schema 。
由于 TypeScript 在运行时均被擦除,以至于我们在运行时无法得到这些信息。所以在之前的分享文章中我们使用了Zod这一个库进行了 Schema 定义,它的核心作用是,将类型信息保留到了运行时,parser 也是建立在这一核心作用之上的。
关于 Zod 的作用及用法,文本不再赘述,这次带给大家的是同一赛道的另一个选手 @effect/schema。
@effect/schema 相较于 Zod 的不同点有以下几处:
更贴近函数式的编程风格。与 Zod 的 class 实现有着较大的差异,具体使用时,@effect/schema 对于类型的组合使用上会更贴近 TypeScript。使用 Zod 时,有时会因为「某个组合子的组成类型要求是某个类型的子类」而无法组合,比如 discriminatedUnion,只能组合 ZodObject 而不能是其他的复合的 ZodEffect 。
更纯粹的抽象定义。Zod 的主要目的更多的是 schema validation ,而 @effect/schema 则可以看作只是类型的一个 AST,只专注于“描述”,因此基于它可以有更多的应用可能性。
内置的 fast-check 支持。这原本是一个基于 Property 的测试框架。利用它可以产出随机数据。
当我们已经使用Schema时,实际上就可以在运行时获得我们的数据类型定义,因此可以通过编码的手段,产出对应类型的随机数据。这里我们直接借助 fast-check 的能力,来实现这点。
举个例子:
5个步骤,手把手带你实现
首先在项目中安装必要的依赖:
和之前一样,我们将 tsconfig.json 调配至合适的选项:
对请求库 wretch 进行封装。这是一个和 axios 一样用于处理网络请求的第三方库。我们对项目内的所有API请求构造器都要求传入一个 Schema 来达到 parse 和 genMockData 的作用。
上述代码通过 parser 已经达到了对接口响应结果进行类型校验的效果,这个做法思路和上一篇文章并无二致。本次的重点在于 mockFetch 的部分。这部分的代码如下:
可以看到核心是劫持了 fetch 的使用,然后用 fast-check 和 @effect/schema/Arbitrary 对Schema进行了一个mock数据的产出并结合授权状态进行返回处理。
在API构造器中具体使用时,示例如下:
当程序代码调用 rowDataCount("my-table") 时将会有两种情况:
有后端联调环境时,程序将会验证GET /model-mappings/legacy-dl/table/my-table/row-count 的返回值是否为 number
以 mock 环境启动时,程序将不发生真实的网络请求,而是会随机生成一个 number 返回给调用处
至此,通过 Schema 获得 mock 服务能力的代码,已经完整呈上。
总结
Mock服务有助于前后端分离形式的项目前后端并行开发,减少阻塞时间。在需求确认完正式编码之前,先约定协商好接口所用Schema,便可以按照约定各自编码实现。前端同学也不会因为只定义了类型而进行“盲写”并且无法启动真实的UI组件渲染。
这个方案在使用了API + 运行时类型校验器 的前提下,几乎是“免费”获得的能力。虽然本文实操是使用了「wretch+ @effect/schema」的第三方库,但是相同的逻辑下 「Axios+ Zod」依然可以达到类似的效果,Zod的生态下也有Mocking能力的实现。有兴趣的小伙伴可以就前一篇文章分享的文章,继续增强以获得相同的mock能力。
继续打开脑洞
现在后端的实现语言是Java而非TypeScript,因此定义在前端项目中的Schema和Java依然有着不同步的小问题。
而Schema本身如果只是一个AST,就意味着还可以继续写个解释器,目标是生成Java interface,作为module或者jar直接进入Java世界中对类型进行约束,团队使用TypeScript作为统一的领域通用语言,接口返回值发生变更时,只允许修改Schema来重新生成Java interface。
如此一来便可一份Schema同时约束前后两端,通过静态类型的作用,变更的影响范围将会被检查出来。
各位小伙伴,假如我填了坑,那时再见吧 👋
本文作者|林金旭
知微前端开发工程师
分享
收藏
在看
点赞