共计 2946 个字符,预计需要花费 8 分钟才能阅读完成。
fst-json 的全称是 “fast-safe-typescript json”,它的实质就是间接应用你定义好的 Typescript 文件,来生成更加高效的序列化办法。
其目标是利用现有的资源(开发过程编写的 Typescript 文件),在编译和开发阶段尽可能进步运行时性能,同时这个过程并没有额定的开发累赘。
github: https://github.com/aircloud/f…
背景
因为 JSON schema 这个概念是由 fastify 引入,咱们先对此进行介绍。
fastify 是一个高性能 Node.JS 服务端框架,其特点就是高性能,而之所以高性能次要的起因就是它引入了 JSON schema,通过对参数减少束缚,来取得更快的序列化速度。
同时,fastify 也开源了一个独立的 json 序列化库 fast-json-stringify,能够在 非 fastify 的我的项目中应用。
在 fastify 中,JSON schema 的大抵写法如下:
const schema = {
schema: {
response: {
200: {
type: 'object',
properties: {
hello: {type: 'string'}
}
}
}
}
}
fastify
.get('/', schema, function (req, reply) {
reply
.send({hello: 'world'})
})
咱们能够看出,这一套写法不仅会带来额定的学习老本,而且因为目前大多数我的项目开发都是采纳 Typescript,这套定义也会和咱们的 Typescript 定义有所反复。
事实上,尽管下面的示例代码比拟短小,然而在理论的我的项目中,接口比拟多的状况下,这些代码的开发量和额定的学习 / 保护老本还是不容小视的。
那么有没有可能间接应用 Typescript,而不必从新定义 JSON schema 呢?
答案是有的。
fst-json 就是这样一个工具,它能够通过复用咱们在 Typescript 中定义的 schema,通过工具主动生成 fastify 须要的 schema,这样咱们就无需额定保护 schema 定义了。
应用形式
接下来,咱们简略介绍 fst-json 的应用形式,首先装置(全局或者装置到我的项目中):
npm i fst-json -g
假如咱们我的项目采纳了 Typescript,当时曾经有了 schema 文件:
export interface HellWorld {
attr1: string;
attr2: string;
attr3?: string;
}
咱们在我的项目目录下新建 .fstconfig.js,用于申明配置,配置如下:
module.exports = {
sourceFiles: ['./src/schema/*.ts'],
distFile: "./src/schema-dist.ts",
format: 'fastify'
}
之后咱们运行:
fst-json gen
而后此时会生成一个 src/schema-dist.ts
,这里会有主动生成的 JSON schema 定义,接下来咱们在我的项目中能够同时应用 JSON schema 定义和咱们之前定义好的 Typescript 类型:
import * as schemas from './schema-dist';
import type {HellWorld} from "./schema";
const schema = {
schema: {
response: {200: schemas.HellWorldSchema}
}
}
server
.get('/', schema, function (req, reply) {
let res: HellWorld = {
attr1: 'hello',
attr2: 'world',
attr3: 'optional'
}
reply
.send(res);
})
当然,fst-json 不仅仅能够在 fastify 中应用,也能够在任何其余须要 JSON 减速的中央应用,用法也都很简略,能够参考这个 HelloWorld
原理和劣势
fst-json,实际上是通过对 Typescript 进行语法树解析,针对 export 导出的各种类型生成对应的 fast-json-stringify 的 JSON schema,所以运行速度和手写是没有区别的。因而,它不仅仅能齐全应用 fast-json-stringify 的效率劣势,除了缩小反复开发量以外还有如下长处:
- 依据 schema 进行字段校验: 首先会进行 Tyepscript 语法校验,另外当缺失必须的属性(例如,当定义 interface 时没有被
?
修饰符润饰的属性缺失)的时候也会间接报错。 - 过滤不须要的 schema 字段: 例如当把 Node.JS 当作 BFF 层的时候,能够严格依照 Typescript 的定义来返回字段,防止返回不须要的字段,从而防止上游服务的敏感字段被间接透传出去,也意味着从接口层面开始,真正做到 Fully Typed。
- 更快的序列化速度: 依据 fast-json-stringify 的测试,能达到靠近 2 倍的 JSON 序列化速度。
目前,fst-json 对罕用的各类 interface、class、type 等类型定义都进行了反对,并且减少了各类 examples 和 90% 的覆盖率测试。
当然,因为 Typescript 的写法比拟灵便。出于 JSON schema 自身的局限性,咱们无奈笼罩所有场景,所以也能够参考这里的注意事项,有针对性的对比拟容易出问题的写法进行躲避。
局限性
fst-json 只是语法解析和生成工具,具体的运行时,实际上就是在应用 fast-json-stringify,也因而我的项目中须要装置 fast-json-stringify 依赖。
另外,针对 fast-json-stringify 的测试,在比拟小的 payload 的状况下,它的速度是有劣势的,当 payload 过大的时候,它的劣势不再显著,甚至还不如 JSON.stringify。官网的形容是:
fast-json-stringify is significantly faster than JSON.stringify() for small payloads.
Its performance advantage shrinks as your payload grows.
不过事实上,这个时候你依然能够应用 fst-json 做一些事件,例如笔者应用 fst-json 来做 bff 层对上游服务接口的继续集成兼容测试,在 Typescript 曾经提前定义好了的状况下,每次测试的时候只须要申请依赖服务并且把响应字段序列化,如果没有报错并且字段序列化之后也没有变成 null(在比较复杂的接口定义中,如果个别属性定义类型和返回类型不统一,fast-json-stringify 是会间接转换成 null),就阐明接口是没有变动的。能够无效防止依赖服务接口变动,却又没有及时同步到位造成暗坑的状况。
另外,其实目前 fast-json-stringify 生成序列化代码还是在运行时做的,这里的问题可能在于代码不通明,以及运行时开销和危险,笔者是心愿将它的生成代码变成编译时去做,不过这样的话实际上有一点反复造轮子的错觉,所以目前还没有做这个事件。
最初 fst-json 作为一个开源不久的小我的项目,必定还有些须要优化和欠缺的中央,欢送 star 反对和提出倡议。