在百花齐放的前端圈,层出不穷的组件框架已让前端开发者应接不暇,另外,再加上业务和开发团队的不断发展,前端开发人员面临的问题越来越多。日渐突出问题主要为:如何高效的与团队成员进行合作开发?项目越来越多,不同技术栈的项目如何统一维护?如何制定和践行统一的开发规范?如何高效的部署和发布产品?
这个时候前端工程化概念的出现,解决了上面让开发者头痛的问题。它旨在制订规范化的前端工作流,并规范统一项目的模块化开发和前端资源,让代码的维护和互相协作更加容易更加方便。同时,让大家能够释放生产力,提高开发效率,更好更快地完成团队开发以及项目后期维护和扩展。
但是前端工程化具体是如何实践的呢?带着这样的问题,我们采访了参加本次 ArchSummit 全球架构师峰会的腾讯 Now 直播产品 IVWEB 团队社区、工程化的负责人——程柳锋,程老师与我们分享了腾讯 Now 直播在前端工程化上的具体实践方案。以下是本次的采访内容:
InfoQ:请您先做下自我介绍吧。
程柳锋:我是程柳锋,来自腾讯,先后参与腾讯 NOW 直播、NOW 语音交友、手 Q 群视频、群送礼等与直播相关的的泛娱乐产品的开发。另外我还是整个腾讯 IVWEB 团队社区、工程化的负责人。现阶段主要关注团队的工程化建设,包括新技术的预研和落地,另外也积极探索行业前沿技术比如:WebAssembly、PWA 等。
InfoQ:一线开发人员参与前端项目过程中需要关注哪些因素?
程柳锋:在产品迭代过程中,前端的定位往往是处于应用层,负责 UI 开发和用户交互体验的工作。大家日常开发时接触的 To C 的产品居多,比如 BAT、美团、滴滴等大厂的产品。这类产品的量级比较大,基本上日均 DAU 能达到几百、几千万,甚至过亿。因此,这类产品对用户体验要求非常高,一个微小的 JS 脚本错误很容易引发血案。
以我们团队为例,对于每一位开发者都有较高的专业能力要求,通常归纳为三个要素。按照重要性顺序如下:
首先,是质量,开发者做出来的项目,其质量必须得到良好的保证,我们也会在项目上线前通过完善的监控手段保障质量。比如:JS 脚本错误监控、接口成功率监控、测速监控、HTML/CSS/JS 加载成功率监控等等。
其次,是产品的性能。我们希望页面加载时首屏的白屏时间尽可能短,至少达到秒开的加载体验。另外,还需要保证在弱网络的情况下,页面也能够很好的展示。
最后是研发效率,就是如何在较短的时间内,快速地进行业务需求的开发和上线。
InfoQ:现在腾讯上线前端项目,或者说升级项目版本,大概需要多长时间呢?
程柳锋:上线时间会根据具体的项目类型地变化而变化。我们内部整体采用敏捷开发模式,通常一个项目从启动到上线在 2~3 周,其中一周为开发时间,一周为测试上线的时间。
另外,对于重点攻坚项目我们之前也有大胆的尝试。举个例子,在 2018 年年初时,直播领域里的答题玩法特别火爆。各家直播平台比如:花椒、映客、熊猫直播,包括腾讯、高德地图、支付宝等都在做直播答题的应用。我们当时做这种攻坚项目,第一个版本从产品方案设计到最后上线发布仅仅花费两周时间。相对来说时间还是非常紧凑的,对一线开发人员作战能力有着较高的要求。
InfoQ:前端工程化是您负责的重要工作之一,它都包括哪些内容呢?
程柳锋:前端工程化是一个团队的基础设施之一,它更加偏向工程架构、研发流程相关的内容,主要有这样几个目的:
随着业务的快速发展,产品需求爆炸式增长,团队成员不断扩充,前端工程化的首要目的就是满足快速发展的业务需要。前端工程化需要标准化研发方式、研发流程(开发、测试、发布、线上监控),让大家从创建项目到最终项目上线、监控使用相同的开发习惯。这个是前端工程化的主要目的。
第二个目的,把团队的经验(比如做项目时踩的坑、经过试验得以验证的新特性等)沉淀到脚手架和开发套件中,使其他同学在开发新项目时可以复用这些经验。
第三个目的是关注新技术的前端工程化落地场景,比如最近比较火的 Serverless、Flutter、小程序等技术。通过工程化的方式把新的技术与现有项目结合进行试验,试验成功后抽成脚手架和开发套件,其他同学后续开发这类工程也特别简单,节省了其他同学再次探索新技术的时间。让整个开发体验更加顺畅。
InfoQ:前端工程化是什么时候提出来的?背景是什么?
程柳锋:大约在 2010 年左右前端工程化的概念开始萌芽。前端工程化的提出,主要有以下两个原因:
业务场景的不断的复杂,很多事情需要前端去承载。像 H5、跨端应用,以及现在 WebAssembly、PWA 等新技术,他们的出现都让浏览器端可以承载的事情更多了,很多业务逻辑由服务端、客户端迁移到了前端。
2009 年 Node.js 的兴起给前端工程化提供了工具层面的支持,现在大家写的构建工具、脚手架工具、代码规范检查,以及我们做的 Pre Render,都是在 Node.js 的基础之上做的。前端工程化的概念还需要通过工具来加以践行和佐证,我们通过 Node.js 编写 CLI 或基于 nw.js/Electron 的 GUI 工具,在项目的创建阶段,大家可以使用统一的命令来创建项目、页面或组件;在项目的开发阶段,针对不同技术栈的项目可以使用不同的开发套件进行本地开发、调试、和规范检查。
InfoQ:从 2009 年到现在也有 10 年的时间了,你觉得现在前端工程化大概发展到什么阶段了?
程柳锋:前端工程化的价和团队规模成正相关的关系,团队规模越大,工程化的价值就更高。可以分为几个阶段:
第一个阶段:初创的团队,团队人数大约在十人之内,这时候前端工程化的主要作用是规范开发、协作规范。这个阶段团队人数相对比较少,大家通过简单的规范约束基本可以满足需求。
第二个阶段:团队规模在快速扩大,内部员工流动比较大,这个时候让大家都遵守之前制订的规范是比较困难的。通过工程化的 CLI/GUI 工具、脚手架、开发套件和插件,保证项目从创建到本地开发、测试,再到最后的发布、监控都能够正常的运转。
第三个阶段:团队如果达到一定规模(大约在 100 人以上),或者多个部门共同参与前端工程化的建设,从而有效的避免不同部门重复造轮子的现象。
InfoQ:在前端工程化的趋势下,CLI 和 GUI 这两个工具开发的背景是什么?解决了什么问题?
程柳锋:如果把前端工程化分层的话,CLI 和 GUI 就是在最顶层。它们是直接和开发者进行交互的,最核心功能是规范开发流程。CLI 是命令行的形式,GUI 是图形界面的形式。中间层即是工具平台和规范,开发者通过 CLI 或 GUI 即可调用工具平台,快速打通与工具平台、开发规范的联系。底层为基础设施。我们目前已在五个业务场景应用了 CLI 工具,分别是五个不同技术栈的业务场景:商业化的运营活动、APP 内嵌的 H5 页面、ReactNative、Serverless、组件。
InfoQ:前端工程化的脚手架能为开发人员缩短构建项目的时间,同时提高开发的效率,请您说一下前端脚手架的构建现状。可以从腾讯的构建现状或者业界的构建现状来讲一下吗?
程柳锋:这两个都可以说一下。我们先来聊一聊整个行业的形态,现在市场上比较流行的前端框架主要是有以下几个:React、Vue、Angular、Weex。这些框架各自所对应的脚手架都只能开发自己技术栈的项目。而实际开发中,我们需要面临不同技术栈的开发场景,单一技术栈的脚手架无法满足需求。
其次,使用的官方脚手架所包含的功能是最基础、最通用的。在腾讯的实际业务场景中,针对一些细粒度化的业务仍需要做二次定制。比如日常中需要上报的各种数据:监控信息、JS 数据、VIP 白名单日志、接口接口调用成功率、首屏渲染时间、HTML/CSS/JS 加载成功率等,用行业通用的脚手架完全不能满足我们的要求。我们在行业脚手架的基础上进行维护,二次定制具有我们业务特色的脚手架。
我们团队目前在这个背景下做了一个更加通用的技术方案。该技术方案基于 Yeoman,在 CLI 里面的集成了 Yeoman 的 Runtime。截止到现在为止,我们公司内部总共有十个脚手架左右,大家可以共同维护这些脚手架,并进行二次定制。通过上层统一的 CLI 命令在创建项目时就可以选择使用哪个脚手架。
InfoQ:现在前端使用 Webpack 构建工具比较多,与之前使用过的构建工具相比,Webpack 的优点是什么?
程柳锋:我个人之前用了很多种构建工具,如 YUI Compressor、Grunt、Gulp、Fis3 和 Rollup 等,目前我们已经完成大部分业务从 Fis3 切换到 Webpack4,其中他们的区别主要有以下几点:
从插件生态上来看,Webpack 相对 Fis3 拥有更高的维护频率(即发版节奏快)。从 Webpack1 到 Webpack5,基本上每年出一个新版本。目前 Webpack4 已经正式发布了,Webpack5 也已经在 alpha 阶段,整个社区 Webpack 贡献者也很多,当大家遇到问题并提交 issue 至社区,问题都可以得到解决。
另外,Webpack 可以做的事情有很多。整个社区的 Loader、插件十分丰富。比如 HappyPack,其多进程多实例打包方案可以实现快速打包,相对 Fis3 来说,其打包效率是非常高的。包括现在 Webpack 官方也原生提供了 thread-loader,也可以通过它进行多进程多实例的快速打包,从而让打包时间得到极大的优化。
Webpack 和其他构建工具的差别在于 Webpack 打包理念是革命性的。Webpack 把所有的资源都当做模块(比如 JS、CSS 图片、字体,或富媒体的文件等)。与其他构建工具相比,Webpack 最显著的特征是它通过各种 loader 去处理模块,这也是大家为什么一直叫 Webpack 模块打包器的原因。Grunt 和 Gulp 的构建过程都是以 Task Runner 的方式去做的。Gulp 是流式的构建,而 Grunt 每次的构建产物会存储到本地的 tmp 目录中,Gulp 是直接放到内存里,构建的时候相对 Grunt 更快一点。
InfoQ:腾讯把构建工具从 Fis3 迁移到了 Webpack4?在切换的过程中有没有遇到什么困难呢?又是怎么解决的?
程柳锋:我们当时切换的时候确实遇到了很多困难。第一个困难是 Fis3 里面支持了一些比较好的特性,而在 Webpack 却没有。这里面也可以举一些我们在实际迁移过程中遇到的例子,比如说 Fis3 支持 inline 语法,可以将 HTML 片段引用到另外一个 HTML 中,也可以将一个图片 inline 过来自动 Base64,还可以合成雪碧图,总的来说它可以精细化的控制资源。但在 Webpack 中是不支持 inline 语法、雪碧图的合成。我们解决的方案是实现相关的 Loader,比如 inline Loader。对于雪碧图的 sprites-loader,在项目迁移的过程中我们把 Fis3 的资源内联语法(?__inline)和合成雪碧图语法(?__sprite) 做了下兼容,新旧项目中都支持了。
其次,Fis3 中支持资源引入时的绝对路径写法,在迁移至 Webpack4 的过程中也需要对它做兼容支持。
还有一个比较大的差别就是打包方式的不同。用 Fis3 打包时是以 HTML 为入口,但在 Webpack4 中是以 JS 为入口,打包的入口发生了很大的变化。这时候,我们也需要对之前的逻辑做些适配。
InfoQ:各个项目中使用的技术栈大不相同,这对项目组件化带来了什么样的影响?
程柳锋:这其实会带来的一个最大的影响是,不同技术栈项目的组件无法复用到另一个项目。所以针对于组件化的复用,我们也做了一些适配,当然,不是所有的组件都适配,我们只是对基础的组件做同构。上层的业务组件可以复用同构好的基础组件。同构相对来讲比较难,但为了之后维护的便利性也是值得的。最好还是根据各自的技术栈实现不同的业务组件,并统一维护。
InfoQ:腾讯 NOW 直播产品在团队工具链、规范等开发配套设施的建设过程中遇到了哪些问题?
程柳锋:这里面我们也是遇到了不少问题。我先从规范说起吧。
我们团队成立之初,是从腾讯的 IMWEB 团队孵化出来的,这时我们的工具链大多延用他们的工具链。随着这业务的快速发展,暴露出很多业务自身的痛点,原来的工具链无法满足现有需求。为了解决这个问题,我们建立了新的工具链和规范。我们首先建立了 Git 提交规范、Git 工作流规范、分支规范、README 规范、监控规范等。但是规范建立之后又面临另一个巨大挑战:如何将这些规范落地实施呢?我们在这方面做了很多尝试:
将 ESLint 的检查规则集成到我们的基础设施上,就是将 ESLint 集成到 CI 和 CD 的流程中。当大家提交代码后,第一步会通过 ESlint 来检查代码是否通过,如果没有通过的话,就会拒绝本次构建,当然这个 ESLlint 检查只是增量检查。如果通过才会进行构建流程。这就是我们 JS 规范的落地执行过程。针对 Git 分支规范和提交规范,我们每天通过邮件扫描,查看前一百条的 Git 提交记录格式是否正确,若有问题,我们会邮件知会相关同学。
业务监控告警的规范执行,主要是靠技术负责人 Review,在项目每次发布上线之前,技术负责人会 Review 监控上报的项有无缺失。同时我们根据业务的重要性、访问量等指标将业务分为 3 个级别:重要业务、常用业务、普通业务。不同级别的业务的监控要求也是不一样的。
除此之外我们还需要强制地将重要业务加到我们的 CI 和 CD 流程里,就是单元测试和端对端的测试,每次代码 Commit 都会异步的通过腾讯的蓝盾进行单元测试和端对端测试,如果测试用例不通过,则不允许发布上线。
另外在工具建设的落地方面,我们会做很多工具平台,比如监控平台、移动测试代理、组件平台等,但这些平台怎么落地?我们也做了一些操作。以监控平台为例,我们会把每个业务对应的 JS 错误 ID、JS 报错率统计出来,并做一下排名。对于排名靠后的项目,会把相关人员、业务的名单展示出来,并通知相关的技术负责人、业务老板等。这个做法还是比较好的,有利于大家及时发现问题和解决问题,同时也帮助整个团队改进工具平台。
InfoQ:在前端工程化的发展过程中,腾讯 Now 直播产品经历了怎样的技术架构变化?
程柳锋:一开始腾讯前端工程化的建设与其他公司还是有一定的差距,甚至说是落后的。最开始我们团队的前端工程化局限于 Fis 构建的工程化。Fis 可以很好支持本地开发,但不支持创建项目、单元测试、端对端测试、代码检查的工程化。所以我们第一阶段做的事情就是换掉 Fis,使用 Webpack 作为我们的构建工具。
之前,整个腾讯 CI 这块的建设比较落后,CI 做得事情也比较有限。在做了脚手架和构建工具切换后,我们团队搭建了 Jenkins,以便于代码的可持续集成。
搭建了 Jenkins 之后,接下来慢慢的迁移到整个公司,并接入了橘子 CI(Orange CI),借助 Orange CI 把很多 CD 的事情也一起做了。因为之前接入的 CI 还不彻底,我们 CI 完成之后,开发者仍然需要在平台上面手动的点击发布,预上线发布还是有很多的人工操作。但我们 CI 完成之后,每次 CI 完成之后它会自动构建出一个包。
如果是正常的 push,默认情况下,构建出来的包会自动的部署到测试环境,完成测试环境的部署任务。
如果打了一个 tag(就是运行 Git tag),或者在 CLI 运行了 deploy 的命令,这时它会自动的帮我们把构建出来的包发送到线上。对于离线包,它也会发一个灰度离线包,我们只需要验证没问题之后,自己再手动的发一个离线包即可。在有了 CI、CD 做支撑后,前面提到的规范和端对端的测试用例、单元测试等,都可以很好的集成进来了。
这就是我们 Now 直播产品整个前端工程化的技术架构,接下来,我们也会去重点探索一下小程序、Serverless 的前端工程化要怎么做,这也是目前腾讯开源协同的 Team 在关注的事情。
InfoQ:那现在腾讯这边的前端的发布系统已经可以实现项目自动部署了吗?
程柳锋:现在已经完全实现自动发布了。CI 和 CD 的过程很大程度上提升了我们的开发效率。之前如果手动发布项目,你需要做很多操作。但是现在只需在不同的发布系统里面点击一下就可以实现项目发布,发布时间从之前 15 分钟优化到仅仅一条命令就完成。
InfoQ:您认为前端工程化在未来有哪些机遇和挑战呢?
程柳锋:我认为有以下几个机遇:
前端工程化可以做很多事情,前面提到了有三个阶段,那么第四个阶段就是中台化,我们可以联合多个部门共建前端工程化,让它的生态和体系更加完善,从而有效的避免重复造轮子的事情,这是每个公司未来都要重点实践的事情。
前端技术发展异常活跃,新的技术和框架不断的出现。对于新的技术方案,我们要及时的把它们整合进来,并探索它们的工程化,比如说像小程序、Flutter、Serverless 等这些新技术的工程化方案。
我们认为前端工程化未来的定位将更加超前。新技术的预研有很大一部分是放在前端工程化中来做的。举个例子,之前我们的项目是 React 16.2.0 版本,这个版本我们用了一年多,但随着 React 框架不断的发布,当 React 发布到 16.8.0 的时候,React 会带来很多新特性,如果再用之前的 16.2.0 版本,开发者将无法感知 React 的新特性。这时候,通过前端工程化的方式,可以帮助大家快速的体验新特性。另外,还包括一些技术方案的尝试,比如像 WebAssembly、PWA 等,通过前端工程化的方式,能够更好的赋能我们业务。
评论