字节三年,谈谈一线团队如何搞工程化一(全景篇)

前言

小编所在的团队叫 "Cuckoo FE" (Cuckoo:布谷鸟,多数种类为灰褐或褐色,喙强壮而稍向下弯,一只幼鸟一天能吃39只蚱蜢),寓意朴实能干,下文中工程化实践各类体系也是以Cuckoo开头。

目前前端团队成员接近20人,归属字节商业化业务中台,承担海外商业化交易流程建设,为字节内部出海产品提供商业变现能力,整体技术方向以PC中台为主(90%+),另外包含部分移动端项目。

从一个故事说起

小马加入公司不久,最近刚接手一个新需求。凭借以往经验,这是一个small case,很快的给了排期,准备开干。没多久,他就向他的mentor提了第一个问题:"怎么创建项目?",mentor很快就丢过来一个仓库,并回复道"你拿着这个项目去copy下改改"。小马愣了一下,不敢多问,立马开始操作,一顿CV猛如虎,项目终于跑起来,心想"快了,只要项目跑起来就快了"。接着小马在开发过程中遇到一个比较通用的功能,又问mentor有没有类似组件,没多久mentor又丢过来一个仓库,并在链接下评论:"你在xx文件下找找xx组件,应该修改修改就能用",小马又把项目跑起来了,细研究了源码,果然能用,很开心又解决了一个问题。这样类似问题一个接一个,mentor也都能很快的给出答复。时间很快,在mentor的加持下到了联调那一天,小马心里长舒一口气"终于可以用真实数据跑一把了",结果在浏览器刷新的那一刻,页面白了,虽然屏幕有点脏,但显的格外的白,这终究还是没有超出预期啊。这一调又是一堆问题,要么是成功码不对,要么是该有的字段没有,有了结构也不对,小马跑过去问后端怎么回事,后端回道"你应该没看最新文档",小马打开文档对比了下:"嗯,是已经有很多不一样的了,但和现在的接口返回好像也不完全一样吧",最终小马还是选择了相信接口返回的json。又是一顿折腾准备提测,小马又问mentor"怎么部署啊?",mentor毫无意外的又丢过来一个文档,好一点的是这次只有一个文档,应该比较简单,点开的一瞬间又绷不住了,里面是一堆文档的链接,有什么编译的、部署的、环境配置的、权限配置的、流水线校验等等。此时小马已经濒临崩溃,但也只能硬着头皮挨个看,挨个对接,但总有地方报错。去查文档,但文档点开总有其它文档,点不完,有时还会有好几篇相同的文档,但说法却不尽相同(小马心里苦啊,他要的只是一个button,轻轻一点就能部署罢了)。作为新同学,小马只能一遍又一遍的问自己的mentor。

终于经过小马几天持续奋战下,mentor也很给力,项目完成了提测,虽然晚了几天,mentor拍了拍肩膀鼓励道"没事,你还不熟悉,后面就会变好",小马心里也很庆幸"能遇到这么好的mentor,不然一行代码也写不了",但回头望着工作桌面满屏的文件夹,又总感觉哪里不对。

小编同学加入字节3年半,所在的团队从开始的几个人到现在的接近20个人,团队成长过程中也遇了一些和小马类似的问题:研发资产沉淀不足、规范不统一、文档缺失、不正确,dev ops 流程不顺畅等等,我们答案是"做好团队工程化体系建设"。但作为业务团队,一切以业务为优先,没有足够的人力投入的工程化等基建上怎么办?所以我们建设的重心有两点:

一,业务团队要做好与公司基建、社区沉淀的连接,尽量利用已有的解决方案快速融合到自己的团队,不做底层的重复建设。

二、做好团队上层沉淀,围绕团队内部个性化诉求打造高效解决方案。

接下来就一起看看在工程化上我们到底做了哪些事情吧,同时也打个小广告,我们准备把这些技术建设写成系列文章(系列主题见下图)分享给大家,欢迎和大家一起交流。

什么是工程化

前端工程化定义

前端工程化作为软件细分领域中的一种技术理念目前并没有明确的定义,它是在15年webpack诞生后开始被越来越多人提及,从开始的打包工具到现在的各类开箱即用解决方案,能力边界在不断扩展。目前社区内基本的共识是以降低成本、提高效率和质量 为目标,以流程、工具、规范 为手段的实践体系。它是基于实践的一系列解决方案,而非单独某种问题的答案,用一句话概括即前端领域内一站式解决方案。

工程化的发展历程

工程化源于实践,每个时期要解决的问题不同,按照解决问题层级大概可以分为以下几个阶段:

1.0 页面动态化, 这个阶段标志前端领域兴起,从最开始的简单脚本到以JQuery为代表的各类工具库百花齐放。

2.0 模块化阶段, 这个阶段主要解决大型应用的开发难度以及开发效率问题 产品代表有国内一线互联网的一系列大型应用如淘宝网,技术则有webpack为代表的构建工具以及React 、Vue、Angular为代表应用各类应用框架。

3.0跨平台大前端阶段 ,这个阶段重新定义了前端,前端领域也有了这样一个伟大的宏愿:一切能用前端实现的终将都会用前端实现。比较有代表性的产品有小程序、脸书,在线excel等一系列跨端产品,技术代表有ReactNative、Flutter、Electron等各类跨平台开发框架。

4.0alpha智能化阶段,随着AIGC的兴起,辅助开发,辅助应用生成已经初显趋势,同时AI进化的速度是指数级别的,AI+的智能前端时代未来充满想象力。

现在我们已经知道了工程化是什么,接下来来看下具体的实践吧。

工程化实践

作为一个横向支撑团队我们面对的主要挑战有:

快速响应:业务发展较快,不同方向变现诉求强烈,需要具备能同时支持多条业务线能力。

业务复杂高: 面对业务形态多样,国家、用户群体各不相同,个性化差异大,整体业务复杂度较高。

质量线就是生命线: 主要和钱打交道,任何一个不起眼的问题都有可能给用户及公司带来难以估量的损失。

面对这些问题已经不是单纯不断加人就能解决的(ps:人也不好加,不是你想加就能加...),为了解决这些问题,我们团队从规范统一、研发资产沉淀、系统解决方案、创新应用逐步建设自己的工程化体系(详见下图),通过这些技术体系建设来不断提高研发团队的上限,这其中最最重要(小马表示真的很重要)的一件事就是"团队规范建设"。

规范建设

为什么要做规范统一

团队刚成立时,人不多,业务发展速度非常快,团队重心是"敏捷",各个小团队各自为战,怎么快怎么来,缺少最基本的规范。但当业务跑了一段时间后,团队已经"敏捷"不起来了,跟不上业务的速度了,我们开始着手做一些基建帮助大家提效,但此时已经不好下手,各个小组用的框架、组件都不相同,只能先从规范统一开始做起。

有哪些规范

按照规范作用划分主要有:流程规范、编码规范、业务规范

如何推动规范统一

制定规范比较容易,但要落地却很难,因为需要对大家有种种约束,如果处理不当容易造成团队反噬,所以我们采用策略是轻拿快放推进要温柔 ,多和团队同学提前沟通,多听取建议,落地要干脆, 对于已经达成一致结论,要结合工具和流程快速落地,阶段reivew落地情况。具体推进过程一般遵循以下三条原则:

规范制定流程标准化, 一般先由规范发起人发起提案(以社区或公司已有规范为模版)-> 团队评审->公示(一到两周)->修改->发布正式版本

落地过程渐进化, 规范落地以增量项目优先,规范从严,存量活跃项目(最近双月有无迭代)渐进接入,非活跃项目最后接入或不接入。

执行过程工具化、运营化,对编码类规范进行卡点工具建设,结合发布流水线中进行规范检测拦截,搭建数据大盘,掌控落地情况。非编码类规范要保持前高后低的运营策略,落地前期(1-2个月)保持高频review,中后期力度递减,定期组织bad case 学习。

通过这一系列的规范建设,已经能解决我们研发过程中很多问题了,我们也在其中发现一个道理:真正的"敏捷"不是快,追求快的结果也不一定是快,一切还是需要遵循事物发展的客观规律"做大做强必须先夯实基础"。

团队规范建设中非常重要的一环就是"统一技术选型",又该如何做呢?

基建建设

统一技术选型

目前底层框架技术选型难度越来越低,各类框架已经越来越趋同,对应社区发展也都很成熟,现在选择更多是基于团队自身沉淀考虑。我们团队早期沉淀以React为主,所以我们团队一开始的技术选型就是围绕React,主要经历三个阶段:自研框架->拥抱社区->回归公司基建:

  1. react全家桶+自定义工程模版+webpack+自定义插件。优点:定制化程度高;缺点:人力投入大,不能稳定迭代,稳定性和扩展性不足;
  2. React 全家桶+ Umi+自定义插件。优点:成熟的解决方案,可靠性很高。缺点:不同插件各个团队重复建设如:容灾插件。
  3. React 全家桶+Eden(字节内部自研)+monorepo。优点:成熟的解决方案,相对定制化,针对内部共性问题,提供了统一解决方案。

我们团队在第三阶段技改时,当时团队内部的仓库已经超过100个,活跃迭代的仓库在40+,其中一个全栈项目有15个仓库,当时维护成本很高,过于分散的仓库也不利于团队技术沉淀及改造,所以我们按照业务分类最终合并成了6个monorepo仓库。

研发物料沉淀

研发物料(组件、模块、设计资源等)沉淀是一个团队最有效的效率提升手段,我们先后完成了组件、物料库、系统最佳实践三个维度的沉淀。

组件 :作为业务团队,我们团队组件建设重心是业务组件领域组件(微应用组件,包含业务数据、权限等,如购物车),基础组件库我们则是基于社区开源组件antd结合团队设计规范进行的二次开发。目前我们沉淀了30+的业务组件,5+领域组件。

物料库: 同部门共建物料库,包含组件、工具函数、区块等代码资源。

最佳实践: 系统级别的解决方案,针对常用业务场景进行案例沉淀 ,设计、PM可以快速从中找到相应资源参考,研发可以配合cli将代码下载到工程中。

中台渲染引擎

在完成设计规范统一和物料沉淀后效率已经有很大提升,但页面配置化才是中台效率的终极核弹。我们得益设计范统一和组件沉淀,自建了交易业务场景下的渲染引擎,实现了90%+ 页面配置化(页面展示、低复杂度的逻辑由配置生成,复杂的业务逻辑额要外编码),开发效率提升60%左右,通常一周的开发量可以缩短到2pd左右。

typescript 复制代码
interface PageDSL {
  label: string
  field: string
  widget: Component
  widgetProps: {
    watch: ['others']
    callback: (info) => {},
    ...
  },
  formItemProps: { //表单描述
    span: number
    initialValue?: any
    tooltip?: React.ReactNode;
    fieldKey?: React.Key | React.Key[]
    ...
  }
  textOptions: { // 表格、详情描述
    type: string
    span: number
    render?: ColumnType<R>['render'] | 'ellipsis' | 'date' | 'time' | 'amount',
    ...
  }
}

当然页面配置化并不是银弹,并不能解决所有问题,我们目前主要还是依靠它来做页面的渲染,以及低复杂度业务逻辑配置,对于复杂业务我们还是需要配合编码实现,而且我们也认为应该用编码实现,主要原因有两点:

与当前团队能力不匹配:业务系统过于复杂,开发完全配置化的系统成本和能力要求很高,目前当前团队是无法完成。

完全配置化不代表的效率的提升:复杂业务导致配置过于复杂,成本高、难度大,如果叠加业务迭代快,成本会陡增,并不会比编码快。毕竟业务逻辑的配置,其理解成本、维护成本要远远高于直观的代码。

脚手架建设

模版-快速创建能力:结合自己的业务特点沉淀了多套工程模版,核心能力是通过命令快速创建项目、页面、模块。

ProCode:得益于渲染引擎的建设,我们通常的开发流程为开发物料->DSL配置->特殊业务逻辑开发,其中DSL的配置约占开发时间30%,这段代码结构高度类似,我们最后通过ProCode来生成这份配置,减少开发时间。生成代码的过程为:读取swagger接口定义->生成基础配置->设计稿图片识别生成页面配置->模版编译+ATS生成页面代码->本地应用更新。

在实践过程中图片识别过程比较困难,先通过oci识别页面有哪些字段,再通过大模型MobileNetV2 来标注组件类型,但效果不明显,生成配置错误多,粒度也不够细,所以我们引入配置预览流程,最后由人工去兜底这份配置。由于目前收益没有到达预期,我们也在尝试由前端编写Figma组件,为研发提供组件及页面区块信息,再通过组件中的文本信息去匹配接口字段(和后端约定每个字段上注释带有字段名称信息),生成更准确的DSL。

质量平台建设

质量建设是工程化中绕不开的话题,我们在漫长建设过程中走了不少弯路,简单概括下可以分为三个阶段:

分散治理,头疼医头,脚疼医脚:初期我们的主要精力对一些突出问题进行专项治理,这些治理工作更多是一次性,一段时间后又会裂化,且质量建设是多维度,很难通过一两个维度的建设来评价总体的建设效果,缺少全局视野的情报。

集中治理,搭建前端视角的质量大盘: 通过性能建设、监控报警等一系列专项建设,我们搭建了前端视角的质量看板,但由于功能和视野比较单一,主要是前端同学在用,对业务反哺不够。

联合治理,搭建全场景业务治理平台:联合前端、后端、QA、PM、数据团队按照业务线维度搭建统一的治理平台,将各方质量建设做到入口统一、数据口径统一、目标统一。

工作台

我们在解决完研发资产的重点问题后,开始着手解决一些研发流程上痛点:

资产管理难:团队100多个项目,每个项目有n条关联信息,靠文档、人去管理非常难(小马表示看文档很累!!!)

开发流程不够顺畅:开发一个项目到上线,需要打开N个平台,过程割裂,学习成本高。

项目治理难:团队内的合规、优化等技术改造专项很多,通过人力one by one去改,周期长,成本高、过程难把控。

我们通过自建研发工作台较好的解决了这些问题,它的主要功能有:

研发资产数据化、可视化管理: 开发项目和工作台共用一套数据源(项目所有依赖为一条数据),保证项目实时最新,摆脱文档管理陷阱,并通过数据可视化的提高管理效率。

研发流程全联接:通过工作台 将研发人员、研发工具(vscode)、公司基建、团队沉淀等整合,具备研发全流程能力,包含仓库及项目创建、项目开发、部署、监控、多语言管理、业务埋点管理、自动化测试、流水线任务等能力,实现了all in one platform。

智能治理: 团队内的技术专项通过创建治理任务结合治理脚本实现自动治理,治理过程流程化,进度可追踪 举个容灾的例子:由任务发起人开发完容灾功能调用治理插件能力(文件操作、git操作、通知、自动化测试等能力),将容灾代码用AST的方式写入到所有业务git仓库中,并生成commit,同时,同时工作台会生成治理任务并推送给业务同学,业务同学在工作台收到任务通知后验收功能,通过后合并代码,任务进度更新,此时就完成了单个项目治理,整体进度也会在专项群里自动定期同步,催办进度较慢的业务方。

创新应用

上述建设更多是研发视角的,那么用户视角又有哪些呢?技术直接下沉到用户侧主要有两块:

首页搭建: 在渲染引擎的沉淀上建设搭建引擎,让用户可以通过拖拽,生成自己想要的首页,实现了千人千面的效果。生成应用过程可以总结为以下公式:

Dashboard = Layout(widget_1, widget_2, widget_n, ...)

Widget = Datasource + View + [Filter + ServiceAPI]

模版服务: 让业务方可以自己配置邮件、合同等各类模版,摆脱了对研发的直接依赖,提升业务方工作效率。

团队技术品牌建设

为了让团队中的技术建设能够持续传承下去,围绕中台、node、移动端技术方向建设了内部的技术品牌站点。

总结

本文主要讲了这几年一个一线团队所遇到过的问题以及从规范建设到实践落地的具体过程,全部是一些内部的沉淀,后续也会按照模块展开讲讲。也希望能和大家一起交流下各自团队遇到问题以及解决方案,互相学习。

最后再补充下这几年做基建的一些个人感受,概括来说就是两个字"难"和"值"。"难"的点一方面是业务压力大,很难有整块时间,另一方面公司基建比较成熟,轮子容易造重复了。"值"的点在于沉淀了一些有价值的东西,提升了团队效率、质量,团队也在这些基础上逐步完成了整个基建的统一。同时我们在建设过程中也总结了一些经验,这里和大家分享下:

保持定力,持续投入: 建设过程中短期可能会遇到各类困难(研发同学压力大、业务很急),但要保持信念,长期看这种投入值得,且时间越久收益也越大。如果遇到是特别特别难的时候,慢一点也没关系,也不要停下来。

敢于尝试,拿得起放得下:短期一些不明确的方向不要怕错,少量投入,快速验证,方向不正确时能果断止损。

以结果为导向, 不自嗨 建设过程中关注实际业务收益,多听取各方建议,避免陷入"我认为很有用"的思维怪圈。

相关推荐
gqkmiss13 分钟前
Chrome 浏览器 131 版本开发者工具(DevTools)更新内容
前端·chrome·浏览器·chrome devtools
Summer不秃19 分钟前
Flutter之使用mqtt进行连接和信息传输的使用案例
前端·flutter
旭日猎鹰23 分钟前
Flutter踩坑记录(二)-- GestureDetector+Expanded点击无效果
前端·javascript·flutter
Viktor_Ye29 分钟前
高效集成易快报与金蝶应付单的方案
java·前端·数据库
hummhumm31 分钟前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
乐闻x1 小时前
Vue.js 性能优化指南:掌握 keep-alive 的使用技巧
前端·vue.js·性能优化
一条晒干的咸魚1 小时前
【Web前端】创建我的第一个 Web 表单
服务器·前端·javascript·json·对象·表单
Amd7941 小时前
Nuxt.js 应用中的 webpack:compiled 事件钩子
前端·webpack·开发·编译·nuxt.js·事件·钩子
生椰拿铁You1 小时前
09 —— Webpack搭建开发环境
前端·webpack·node.js
狸克先生2 小时前
如何用AI写小说(二):Gradio 超简单的网页前端交互
前端·人工智能·chatgpt·交互