sorrycc / blog

💡
4.48k stars 324 forks source link

《蚂蚁金服的前端框架和工程化实践》文字稿 #85

Open sorrycc opened 5 years ago

sorrycc commented 5 years ago

本文为在 GMTC 2019 上分享的文字稿,同步发在《前端之巅》公众号。

开篇

自我介绍

目录

框架发展历史

这是我们的框架发展时间线。

在 Umi 和 Bigfish 时代,我们从刀耕火种的时代跨入了工业化时代。因为在此之前,用户需要接触很多技术栈和细节,在 Umi 和 Bigfish 中,用户只要知道一个框架,剩下的全部不用了解。框架像一个魔法球,把各种技术栈吸到一起,加工后吐给用户,以此来支撑业务。

在两个框架合并之后,我们的现状是这样,

那么,这是我们的框架终局吗?以及是否还有更好的方式?大家也可以思考下,后面在未来规划区域会有探讨。

这是一些蚂蚁的内部数据,

目前来看,这个框架基本统一了内部的框架使用情况,不仅有不熟前端的 Java 开发,略熟前端的外包,还有资深的前端同学。要获得那么多同学的认可,并不是件容易的事。

为什么我们能成?

那么,为什么我们能成?

个人理解,我觉得有几个关键词:

人是非常重要的一环,甚至比技术本身更重要一些。

那么别人为啥要用你的框架?首先,框架要好用,这是最基本的;然后,使用者尤其是资深的前端同学,还得在这上面找到自己的成就感和 ownership,另外如果绩效漂亮就更好了。总不能别人用你的框架,然后只有你自己一个人的绩效好,那是不会长久的。

我们的解法是插件体系。

框架不是凭空而来的,需求来自于业务,所以用框架写业务的同学往往能发现框架不足的点,他们可以开发适用于自己业务的框架插件,反哺框架。如果这是通用需求,那就亮了。

框架的内部开发群有 100+ 人,包含大量来自业务线的同学,这就是插件体系的好处,人人都能贡献。

为了让写插件变得简单,我们给框架分了五层架构。

包含依赖层、插件层、插件集层、应用类型层和部署模式层,大家可在任何一层都可贡献代码,

这是插件生命周期图,包含:

  1. node 环境执行的编译时
  2. 浏览器上执行的运行时
  3. ui 辅助层的编辑时

大部分插件体系只会考虑 node 编译时,我们加上运行时和编辑时的支持,赋予了插件更大的能力。

具体做了什么就不展开了,每个框架都不同,但做的事情其实大体一致,往上说是 html、css、js,往下说还有各种工具的配置,比如 webpack、babel、postcss、dev 中间件 等等。

下面来看具体如何写一个插件,如果大家有写过 vue-cli 的插件,会发现很类似,

我们目前的部分插件,内部流程相关的就没有列出来了,内外加起来应该有 100 多个了吧。

这是我们的分工表,基本上涉及到了框架和业务的方方面面,很多事情都是由不同的人来负责,大家的参与度也不错。

当然,人总是不够的,很多子项都还处于招人状态。

我们的框架能成,我觉得另一个重要的原因是我们不仅做功能,还做业务和流程。我不清楚大家是如何走流程的,包括如何切换应用类型,如何和各种后端服务和平台对接,反正我们的还是挺繁琐的。程序员的时间浪费在这里我觉得很不值,所以如果框架能解决这部分,应该会受到欢迎。

我们通过 appType 和 deployMode 两个维护来对接各种场景,用户只要配 deployMode: node 就能对接 node 框架,改成 java 就能对接 java 框架,背后的脏活累活交给框架做。

最后还有一个原因是我们做开源,我个人是比较热衷开源的,把自己的实现完全透明地展示给社区,包括之前写的工具和数据流方案,也都是从开源做起,因为我觉得开源相比在内网闭门造车,能带来很多好处。

另外,开源做地好,也更容易获得内部同学的认可。包括之前做的 dva、现在的 umi,都不是一开始的内部首选,而是后来慢慢逆袭的。

框架大图

这是我们现在的框架大图。

拳头功能

下面是我们的一些拳头功能。

资产市场

今年由于大形势的原因,我们比较重研发提效,最好是一个人能干 10 个人的活。关于提效,其中比较重要的是相同的代码不要重复写,要做提取和组件化。而资产市场就是做的这件事。

为了更有效地复用,我们对资产市场分了四级,

  1. 组件,指通用组件,就是 antd,在下半年将要发布的 antd@4 里,我们会陆续提取更多通用组件到 antd 中
  2. 业务组件,不能提取通用组件的,我们会提到内部统一的业务组件仓库中
  3. 区块,由组件组成,可以想象成代码片段
  4. 页面模板,由区块组成

我们可以借助工具把区块和页面模板添加到页面中。

通过 Umi UI(可视化方式)添加区块的样式。

区块方案其实不是一开始就这样,中间经历了几次迭代。

这是区块方案的迭代情况,一路踩着坑过来的。

资产市场不会凭空运转起来,或者说我们做了资产市场,大家就会按照这套方案用起来。比如一个产品,设计师不按照约定的规范来设计,那资产市场就成了摆设。所以,这是一件自上而下的事情,并且得拉上设计师同学一起做,才有可能做好。

在工具层面,我们需要打通上下游,同时兼顾三类角色的同学:

微前端

我们在微前端方面也有一些沉淀,并在生产环境有大量应用。

关于微前端是啥?首先大家想到的可能是一个解决多套技术栈共存的方案,比如首页用 jQuery,订单页用 React,客户系统用 Vue。这没错,但是一个相对狭义的理解。

一个问题是,如果我们的技术栈一致,那是否就不需要微前端方案了?不是!

我对微前端的理解是,他不仅是个技术方案,更是个解决流程、组织架构等问题的方案。

比如淘宝网,可以简单理解成有淘宝首页、交易系统和帮助系统,这些系统是优先级的,并且在我们人力有限的情况下,我们会把资深的同学投入到重要的系统里,不重要的系统我们可能会通过外包或者购买的方式解决,但是一个底线是,不重要的系统不能影响重要的系统的运转。

要实现这一点,目前流行的有两种方式:

MPA 没啥好说,成本低,大家都爱用。但如果想要更好地体验,则不妨试试微前端。

微前端的概念其实已经出来 3 年多了,但社区喊地比较多,给方案比较少,在生产环境应用地就更少了。

我们首先是基于 SingleSPA。

这样能 Run 起来,但还只是玩具,要上到生产环境还远远不够,还需要解决很多关键的技术问题。

图中是我们结合实践总结出的关键技术问题。

以上问题,我们都有解决方案,但可能有些还不完美,需要进一步尝试。

这是部分问题的实现原理。

更多实现细节,可以关注文章,分享之后我们会公布。

正如前面所言,我们热衷于开源,所以这套微前端方案在业务上验证过之后,我们就把他了。

这句话不是我说的,大家如果有发现更好的方案,可以找 @有知 探讨下, 😆。

场景完备性

作为一个框架,你得有亮点;而作为一个企业级框架,你得满足需求。而要满足需求,该有的功能就必须有,亮不亮不管,得有,不能让框架成为业务需求的瓶颈。

红色的应用类型方面,

蓝色的部署模式方面,

当前端框架成为内部的一致选择之后,就会被推着去做很多业务方面的事情,适配各种场景的需求。不过好在我们有插件机制,上面大部分的需求都是业务方同学通过插件和我们一起实现的。

专题研究

除了拳头功能,要做一个框架,还不得不在一些专题上有深入的研究,很多知识点是需要彻底搞透的,这样才能知道如何设计更合适。

路由

首先,我们既支持配置式路由,也支持约定式路由。配置式是实际需要,约定式是理想,

功能方面我们最先是参考 next.js 做的,但发现 next.js 只支持简单的路由功能,于是自己做了很多扩展,

由于我们是集中式的路由组织方式,并且管控了路由的渲染逻辑,所以基于路由就可以做很多事,

这个列表每次分享时都会增加,很有想象空间。

这里介绍一个大家可能感兴趣的点,基于路由的按需编译。就是比如我们有 1000 个页面,而调试时只要调其中的 5 个页面,那只编译这 5 个就是最理想的。

这有几种实现方式:

临时文件的实现是这样的,

  1. 先用 Loading 组件占位
  2. 当用户访问指定 url 时,才把相应路由的组件替换进去

虽然有些取巧,但简单有效。

我们的编译是基于 webpack 的,诚如大家所料,启动速度还是比较慢的,尤其是项目大了之后。为了让使用者体验更好,我们在这边也做了很多尝试,有正常的方式,也有不正常的方式,😆。

正常的方式有:

进阶优化的有:

“变态”优化的有:

性能优化是每个框架和每个前端都逃不开的点,从我 10 年前做前端起就关注这个点了,到目前方法有些变化,但性能优化依然很重要。下面我们的一些尝试,

目前为止,因为浏览器的差异,我们仍需处理浏览器的兼容问题。不过比第一代前端需要处理 IE6 的兼容问题已经好多了。

关于补丁方案:

编辑器插件是框架非常重要的配套设施,很多功能在框架层其实没法做,尤其是用了大量的约定之后,编码时会损失代码提示方面的支持,利用编辑器插件就能弥补这一点。

举两个例子,

比如,dva 的数据流方案基于 redux,而 redux 的 action 是基于字符串,很难利用 TypeScript 特性做自动提示。借助 vscode 插件即可做到这一点。

再比如,umi 的路由配置是指向路由组件的路径字符串,框架层做不到提示补全,借助 vscode 插件也可以做到。

测试方面基本上和大家都一样,包含单测、UI 测试、e2e 测试和集成测试,基本方案是基于 Jest + test-react-library + Puppeteer。

但是,大家都知道业务同学很忙,没有太多时间写测试。所以我们如果能有个基于路由的自动化测试方案,让业务不写代码也能确保每个路由都能正常运行,也是个不错的选择。

这是我们的监控体系,有了数据,才能知己知彼,有的放矢。

分构建时和运行时。

构建时在云构建容器层去生成构建报告,我们自研的工具比较好办,但就算在蚂蚁内部,也还是其他工具的存在,比如直接用 webpack 做构建的,或者基于 webpack 封装的。对于这些非自研的构建,我们会用猜测的方式,来定位出他是有什么工具进行构建。

数据层会跑大量的定时任务去做数据清理,提供够展示层。展示层提供排名、大盘、版本分布、竞品分析、出错预警等信息。

运行时没啥特别的,大家的方法都差不多。有一点值得一提的是我们会在云构建平台去自动申请埋点标识并在构建时自动注入,让用户免去埋点标识的申请,所有产品自动就会有数据支撑。

这是一些构建时的数据展现示例。

未来和规划

Bigfish + Umi 的内外结合的方式目前看起来还不错,但毕竟是两个团队妥协后的方案,在我们需要服务外部 ISV 时暴露了一些问题:

虽然底层都是 umi,但内外网同学的使用方式还是有很大差别的,导致我们的方案对外时会有额外的成本,以及我们自己在文档等方面的投入上都需要做两次。

差异主要是,

所以,我们要 让内外网的框架方案保持一致

修改后的这一版是我能预见的框架终态。

2019 年的重要里程碑。

THANKS

参考

i5ting commented 5 years ago

谦哥威武。

Say-healer commented 5 years ago

不错

crixusshen commented 5 years ago

可以借鉴

justjavac commented 5 years ago

大赞

chenbin92 commented 5 years ago

很多点值得学习借鉴,人 -> 框架 -> 开源 -> 业务反哺-> 框架

kuitos commented 5 years ago

微前端相关的话题,欢迎大家找我探讨:smile:

lengjing commented 5 years ago

“云编辑”时代可期,非常看好这种模式。

ghost commented 5 years ago

学到了很多。赞!

EastLee commented 5 years ago

学习的榜样

qiutian00 commented 5 years ago

+1

snakeUni commented 5 years ago

学到了很多!!

anyexinglu commented 5 years ago

秀啊

chaoren1641 commented 5 years ago

作为内部同学,之前一直对 Umi 和 Bigfish 有模糊的概念。既然合了,能否直接搞一个名字就好

DiamondYuan commented 5 years ago

之前很好奇大鱼是做什么的。现在终于知道了。

MuYunyun commented 5 years ago

这么多方案名词会绕晕, 能把它们理清也是不易。膜拜

HandsomeHan515 commented 5 years ago

👍

xiaohuoni commented 5 years ago

👍

jaywcjlove commented 5 years ago

👍 威武

teachat8 commented 5 years ago

谦哥威武。👍

jerexyz commented 5 years ago

大赞👍

dr2009 commented 5 years ago

学习了👍

hzxfjmc commented 5 years ago

应该是个好东西

shenzekun commented 5 years ago

👍

rockyou9000 commented 5 years ago

现场聆听大佬的演讲, 受益匪浅 点赞

txp1035 commented 5 years ago

学习!

Chersquwn commented 5 years ago

👍

jianglin-wu commented 5 years ago

这些基础建设已经是相当完善了,二线公司要跟上还得花好几年时间呢

1eeing commented 5 years ago

猛的一匹

JackFrankWen commented 5 years ago

5年出一剑

hqwlkj commented 5 years ago

赞 👍

zhaoxiaobao commented 5 years ago

干货

ihubcode commented 5 years ago

赞! 👍

jiachaosun commented 5 years ago

微前端内容很不错,已经在研究使用qiankun了

htoooth commented 5 years ago

这都是人的投入啊,没有阿里这么大的规模做不出来这个东西

LuckRain7 commented 5 years ago

get

simdd commented 5 years ago

👍

senro commented 5 years ago

受益匪浅,感谢分享!不过建议把umi官网关于按需编译的文档完善一下,让更多人知道用法

luhc228 commented 5 years ago

学习了

shengbeiniao commented 5 years ago

期待微前端更新~~自己踩了不少坑

tomzhang commented 5 years ago

很棒的实现!但是能够加些当前与后端协作的实现么?比如BFF或者serverless?

ljianshu commented 5 years ago

大佬好!本文可以转载到我公众号?会注明来源和出处的

ystarlongzi commented 5 years ago

难得一见这么接地气的技术长文,收获很多,感谢分享 👍👍

FishPlusOrange commented 5 years ago

学习了,收获甚多

fengyun2 commented 5 years ago

大佬,ppt地址无法访问了

wangyinwei1 commented 5 years ago

umi 现在keep-alive有方案吗?如果有该怎么做

garchinday commented 2 years ago

nice!

FE92star commented 2 years ago

mark