钉钉前端团队原创,点击右上角关注咱们,了解更多前端技术前端
做者: 烛象java
钉钉业务体量已达亿级,钉钉技术的服务端、客户端等的数据模型和接口已达到极高的复杂度。面对多样的客户端和技术栈IO环境,咱们采用了IDL(interface description language)来描述多端数据通讯的约定,以收敛业务复杂度带来的维护风险。node
对于前端来讲,容器环境从mobile、web到智能硬件IOT、桌面端CEF容器;上下游数据源也包罗了Java、C++、Node.js等宿主语言环境。 c++
在多人协做、前端工程化的大背景下,咱们开始大量使用Typescript来加强代码的健壮性、可维护性。本文将分享笔者是如何设计自动化代码工具,以便加速typescript在团队的落地。web
相信大部分前端掘友们都有体感,业务迭代伴随的数据接口、模型改动,都须要前端同窗手动检查业务代码,一旦改动不完全、单元测试没有覆盖分支流程,线上稳定性就极容易收到威胁,做为开发的体感也是极差。typescript
在2017年,借助钉钉桌面客户端从node-webkit演进至native CEF架构的契机,咱们引入Typescript做为开发语言,并逐步使用起ts的技术生态,如rxjs、redux-observable等。npm
从2017年到2018年,钉钉桌面客户端CEF容器中运行的前端代码就已经高达23万行,维护者达到20位。redux
Typescript在钉钉桌面端的落地让推广工做获得了承认,好比钉钉考勤在重构过程当中,逐步从js迁移到ts,开放平台的售卖系统直接就用ts编写、多个内部npm模块编写的语言选型优先采用ts。小程序
But , 本来觉得ts能够在团队顺利推广,然而现实却并不是如此。不少新业务在选型时仍是选择了js,是工程化成本过高仍是ts太难?设计模式
咱们了解到不少新同窗、实习生加入团队就能很快的上手老的ts项目,断言ts语言不是问题源头。
在和业务开发同窗沟通后,咱们发现技术栈从js迁移到ts的过程当中,数据接口定义的编写、ts脚手架的从新熟悉是主要的障碍源。
工程化和研发效率的问题构成了较高的ts研发成本,成本就意味着收益下降。
确实,要想享受ts的类型检查、类型推导、编译期代码检查等便利,前端项目就必须提供数据模型和接口的ts定义,咱们但愿找到自动化生成ts代码的方案来解决这个问题。
在开始介绍咱们的IDL自动化代码生成方案以前,我先简单介绍下钉钉的IDL —— 强有力的多端数据接口描述语言。
钉钉的接口描述(IDL)文件,由model和interface组成,model用来描述数据模型定义、interface描述接口信息。举个例子
/** * model.idl * 网关报错返回对象 */
module test;
struct GatewayErrorModel {
// 是否被降级。1是,0否
1: int isDegrading;
// 安全网关域名
2: string domain;
};
复制代码
/** * interface.idl */
module test;
include test.GatewayErrorModel;
interface GatewayIService {
/** * 上报网关访问异常错误 * @param appId ID * @param host 域名 * @param errMsg 错误信息 */
GatewayErrorModel testRpc(string appId,string corpId,string domain,string errCode,string errMsg);
};
复制代码
以上两个文件interface.idl和model.idl同属一个模块, 模块名由module关键字指定即test,模型和接口的依赖关系经过include描述,数据结构经过struct描述。 model和interface的idl文件,组合构成该模块对外暴露的数据接口。 在钉钉,IDL描述了各端的数据IO信息,不一样代码语言如Java、C++的rpc和推送模型的自动化生成基于IDL。IDL为各端的代码编写提供了一致性保障,让全部的数据和请求都有源可溯。
简单介绍完IDL后,咱们回归上面的问题:如何下降ts对业务开发的成本。
想必大部分读者已经猜到了,咱们的方案即是编写工具将IDL转译成Typescript接口和模型定义,简图以下。
从信息熵的角度来讲,IDL既然能覆盖c++/java等语言的数据约定,它包含的信息确定足够覆盖前端Typescript的定义。
下面用一幅图,简示下dingtalk-idl-ts的实现细节流程。
首先从IDL作tokenizer到AST,再由AST作fs.writeFile生成初步的ts文件,随之根据业务上层传入的语言模块要求(如es、cjs)生成不一样的compilerOptions以供tsc命令调用,最后调用tsc命令行自动生成rpc代码及模块定义。有兴趣的同窗能够私信了解每一个环节的代码实现。
有了自动化生成ts的工具还不够?咱们要将稳定性的要求注入生成的ts产物
为了让数据模型生成的置信度最高,在自动化生成代码的同时,dingtalk-idl-ts工 具对数据模型的property作了optional的处理。 所以任何一行业务层的代码若是对模型的property selector没有作保护,都没法经过编译。
这样的设计模式给业务代码带来了必定的冗余度,但为业务的正确运行和错误溯源作了底线的保护。
自动化代码的生成产物,大体以下:
经过dingtalk-idl-ts提供的命令行工具,业务开发只须要一个命令行,便可按需生成项目所须要的ts数据接口定义,从易出错的手动编写ts代码中解放出来。
如今该工具已在钉钉的桌面端、小程序、H5应用中落地使用,ts的进一步推广也随着基础设施的完善逐渐落地。
以上大体就是咱们在落地Typescript的一些方案和实践,很是欢迎有更好想法的同窗提出意见和建议。但愿读完本文你有必定的收获。
招人时间:
钉钉前端团队社招全面开启,求各路技术达人加入。
简历投递邮箱: xiaogang.hxg@alibaba-inc.com
笔者钉钉号: huangxiaogang
扫码关注更多钉钉技术
![]()
😊钉钉欢迎扫码关注《钉钉技术圈》
![]()
😊欢迎扫码关注《钉钉大前端团队》微信公众号