在过去半年中,我们将达达侧所有前端项目迁移到自动化构建平台,彻底告别了人工操作的低效率和不安全,并降低了等待过程中切换任务造成的出错风险。下面分享一下我们在实践过程中遇到的困难和收获的经验。
背景
过去,前端项目都在本地构建,包括拉取代码、安装依赖、打包编译、上传资源、修改线上配置等一系列步骤。这当中存在许多问题:
• 操作复杂,容易出错(步骤长、命令多、异常情况多)
• 耗时长,浪费了研发人员时间(5分钟以上)
• 有安全隐患,本地构建好之后,代码需要上传到七牛CDN,秘钥存放在代码库,由本地直接上传外网CDN
现在,使用自动化构建来解决上述问题已经成为一项迫在眉睫的任务。
自动化构建原理
在过去的构建发布过程中,所有的步骤都需要开发同学依次手动完成。
首先从代码仓库拉取项目代码,然后需要从npm服务器上下载项目用到的三方库。由于官方npm服务器部署在国外,这一步的下载过程有时会非常慢。接下来并不能直接进行打包,在此之前我们需要手动去升级一下版本号,本地打包完成后将新版本号提交至代码库。由于这个过程与git操作紧密耦合,当多人并行开发时,有一些几率会导致提交冲突。
打包完成后需要将静态资源上传至CDN,这个过程中我们需要用到CDN秘钥,所以秘钥不得不存在代码库中,导致了可能泄露秘钥的安全隐患。由于静态资源在html中引入,所以当新代码发布时,html中版本号需要升级。由于前端的html放在后端部署,我们需要把之前手动升级的版本号通过配置中心去同步到html中。
可以看到,因为人工操作的介入使得整个构建发布的流程变得分散而复杂,许多关键节点需要靠人反复去确认,很难保证永远不出错,如果版本号输入错误,线上页面就会访问异常,需要重新发布,这样一来构建时间的不确定性和线上风险都上升了。
在现在的构建方案中,开发人员在本地电脑无需再做任何操作,只要登录自动化构建平台点击构建,所有的操作就会由平台来完成。
从结构图中可以看到,促进自动化实现的关键之处在于第三步中,我们使用了根据文件内容自动生成的版本号,于是打包过程可以与git操作解耦,无需人工维护。得益于构建平台的统一, CDN密钥我们可以集成在CI服务器内部统一管理,这样每个项目上传资源至CDN时可以直接从CI服务器获取,就无需再将密钥这样的敏感信息存于代码库中了。最后在发布过程中,html不再依赖后端部署,而是通过CI服务器自动上传html至ops平台,由前端独立部署,因此我们也无需再与后端的配置中心交互。
新的构建流程不再分散、需要人工周旋于多个平台之间,实际上从拉取代码一直到部署html每一步都是在CI完成,形成闭环。这使得我们每一次构建发布操作都稳定可控。
提升构建速度
有了新的流程后,我们所有剩余的项目都顺利接入了CI,然而一切并未结束,此时的构建速度还并不能令我们满意。在对构建过程进行埋点后,我们发现安装依赖的环节耗时较高。
原因在于CI平台的构建并没有做依赖包的缓存,如果利用上缓存我们可以节约每一次构建时重新安装依赖包的时间,使构建速度大幅提升。
这里我们使用了docker的数据卷功能来实现依赖包目录持久化。由于之前对docker知识了解不深,开始时遇到了一些困难。我们在使用中发现,docker镜像中只能使用匿名数据卷,会将缓存的文件放在一个随机命名的目录下,第二次构建时就找不到之前的目录了,要复用缓存必须使用具名数据卷。查明原因后我们调整了方案,在启动容器时挂载服务器目录然后执行打包操作。
使用这样的方式我们不仅可以挂载项目内的node_modules目录,还可以挂载yarn的全局缓存目录。在最终版的构建流程中,我们主要通过这三个方面来减少安装依赖的时间:
• 使用项目级缓存
• 跨项目间共用全局缓存
• 搭建内部NPM服务器,减少从国外NPM服务器下载资源的耗时
优化后的流程如下:
从19年7月起我们开始做速度优化,到12月时CI平台前端应用的构建时间下降了超过50%,平均构建时间从4分45秒降至1分56秒左右,每次构建可以节约2分50秒。目前平均构建时间控制在2分钟以内。
在去年10月到11月,达达侧前端45个活跃项目共计发生1607次构建,得益于构建速度的优化,这两个月中我们总计节省了78.7小时,折合约40小时/月。
展望与感谢
至此,我们完成了前端自动化构建的一次完整实践,从无到有,从有到更进一步优化。在未来,我们计划让一些非常规构建的项目也能通过CI平台来构建,如微信小程序等。另一方面,对于一些有并行开发需求的项目,我们正在探索前端容器化的方案,使构建更灵活,更能满足不同项目的需要。
在自动化构建的实践过程中,质量保障部和物流运维部的同学们给了我们很大帮助,不仅配合我们一起实验不同的方案,而且详细地给我们物流前端部同学讲了许多docker镜像构建的原理。物流业务前台部朱荣在构建速度优化时提示我们使用步骤拆解的思路来定位速度瓶颈,对我们后期制定的方案有着至关重要的作用。在此对他们表示感谢!
完