-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
基于 Git、Svn 变更检测实现可增量构建的前端持续集成解决方案 #7
Comments
你好,我是厦门美柚前端,看了你的文章,感觉思想挺不错的,和我们的流程也大体相似。 |
gitlab ci 的配置网上文章应该挺多的,建议 google 。如果你看完 README.md 会发现我们这个任务调度器其实和 gitlab-ci 没太多关系 |
想问下线上构建后的html文件要放在git版本控制里吗?如果要的话那每次构建完就要commit一下,这样就可能会有冲突,需要考虑解决冲突,如果不放,那么每次发布就只能是全量构建,应该没办法做到按需构建吧? |
@gaoshijun1993 构建后的代码不因该放在版本仓库中,这不是 git 仓库的职责 |
请问能否说一下 如何做的增量构建? 我理解增量构建需要利用上一次构建的产物或者缓存. 但在CI的环境里面 这个怎么做到和 构建工具无关呢? |
按照包维度进行对比的 |
我可以理解, 是每个包都有各自的 构建脚本. 当检测到某个包油变化 就进入这个包去执行构建对吗? |
近两年由于技术的发展,Web 前端可以通过编译工具来实现 HTML、CSS、JS 所做不到的事情,从而覆盖更多的业务,从技术角度实现更多的价值。社区也在不断的创造更好的编译、构建工具,例如目前大红大紫的 Webpack。正因为这些先进的工具,我们工作效率得到了前所未有的提升。当然,我们也需要面对它们所带来的一些问题:构建速度越来越慢,导致发布速度越来越慢。尤其是在使用持续集成系统来构建的项目中,这个问题越严重。
解决构建慢的问题有很多途径,比如常见的手段是优化构建工具的配置,网上也有很多这样的实践经验文章,这些优化手段大多都是针对具体的工具、本地开发构建进行的,如果使用持续集成服务器进行构建,社区缺乏一些简单可靠增量构建解决方案。针对于此,我给大家分享我们前端团队(厦门欢乐逛)的实践成果:基于 Git、Svn 的 Commit 实现可增量构建的前端持续集成解决方案。
背景
大约是 2014 年的时候,我们在 Git 服务器上通过 Githooks 、Grunt 实现了一个复杂的前端增量构建系统:提交代码到对应分支后服务器会自动进行增量构建、增量发布。这套系统这在当时看来自动化程度已经很高了,解决了本地构建、发布所带来的效率以及安全风险,版本发布非常快速。当时前端团队的构建与发布流程:
2014 ~ 2017 年之间,我们业务飞速发展,前端项目越来越多,构建这一块也被更先进的 Gulp 与 Webpack 代替,而之前基于 Grunt 设计的增量构建系统已经无法适应新业务与技术的需求,项目部署、团队协作的成本越来越非常高。这迫使我们思考如何实现一个不受具体构建程序约束、跨业务、支持增量构建与发布的标准化解决方案。
决定做这个事情之前,我们先将 Githooks 触发的构建与发布任务由持续集成系统代替,以让前端开发流程与工具标准化。
持续集成
“持续集成是一种软件开发实践。它倡导团队开发成员必须经常集成他们的工作,甚至每天都可能发生多次集成。而每次的集成都是通过自动化的构建来验证,包括自动编译、发布和测试,从而尽快地发现集成错误,让团队能够更快地开发内聚的软件”
以上是持续集成的概念,一个完整的持续集服务由以下几个系统组成:
由于我们公司内部代码托管平台使用 Gitlab 搭建的,因此直接采用了 Gitlab 自带的 Gitlab CI 作为构建服务器,这样能够与目前工作流无缝整合在一起。
上图是 Gitlab Builds 模块的界面,CI 根据我们设置的 Git 分支策略,不断的为我们构建、发布测试环境、部署生产环境的代码。
增量构建
本地开发中,规模较大的项目一般会拆成多个模块,单独进行编译来提高构建速度,根据不同的参数来构建指定模块。
而在持续集成系统中,最初我们通过判断 Git 提交的消息的特殊标记来决定构建哪些模块,例如构建 “users” 模块:
git commit -m "[publish:users] 修复线上 BUG #456"
这种简单的开发约定可以让服务器做到精确构建,不足之处是需要人工介入,存在风险。例如:开发者修改了公共模块后,如果忘记构建依赖了它的业务模块,这很有可能引起线上故障。
理想的情况下,项目开发人员无需关注细节,只需要关注工作本身。测试、生产环境的构建与发布的细节应该完全由持续集成服务完成。
自动增量构建
为了实现完全自动化,我们使用检测文件修改的方式来触发增量构建,不同于本地开发中的
--watch
模式,我们采用 Git 的 Commit ID 来实现。原因:持续集成系统需要明确的知道任务的成功与失败状态,而构建与编译工具自带的--watch
会导致进程常驻,无法获取运行结果。gitCommit.watch()
方法会记录上一次的提交版本,对比新旧提交版本即可决定是否启动构建,从而实现增量构建。这种基于版本仓库的变更对比使用 md5 要高效很多,并且能够让发布后的文件和版本库关联起来。更加重要的是它是成熟的解决方案,这对系统的稳定性至关重要。通过 JSON 声明构建关系
项目中通常都有自己的构建脚本,如果再添加增量构建逻辑这无疑会加剧构建脚本的复杂度、带来更高的成本。因此我们设计了一种描述增量构建的任务的配置格式,然后实现任务调度器来解析它们、运行任务,以实现对业务原有构建流程的解耦。例如:
tasks
是要观察的目标列表,它是文件或者目录;program
是它们发生变更后的处理命令;${taskPath}
被设计为一个变量,运行时解析到当前构建目标。监测外部依赖变更而触发构建
在业务中,免不了需要全量构建的情况,例如:导航的替换需要重新构建所有业务模块。
这种情况下需要添加
dependencies
来描述依赖,以让任务调度程序能够处理依赖。例如公共模块 “common” 发生版本变更,就执行全量构建:如果 Npm 的模块发生版本变更也需要进行全量构建,将 package.json 添加到
dependencies
即可:通过这种依赖声明依赖还有一个好处是:使团队所有人能够快速的了解模块修改导致的变更范围,例如测试同学可以通过 CI 日志准确知道关联模块的变更。
多进程并行加速构建
前端代码压缩是一个 CPU 密集型操作,非常耗时。而大部分前端构建工具都是单进程设计的,因此它们都无法利用多核心 CPU 资源。如果业务模块之间没有依赖关系,启动多进程可以加速运行它们。
tasks
支持并行运行任务的描述格式,使用二维数组即可启用并行构建:遇到可并行的任务,任务调度程序可根据当前机器的 CPU 核心数启动对应的子进程数,实现多核加速。
成果
至此,我们用一个非常简单的技术方案实现了设计目标。由于任务调度器的职责非常简单,不对业务有侵入,因此我们很快速的在几个大项目中完成部署,和业务中原有的构建脚本配合完成增量构建与发布的任务。
上图是我们的一个大型项目,仓库中有 600 个左右的 js 模块。采用增量构建后,持续集成系统从一个版本从代码提交、构建、发布通常一到两分钟即可完成。如果关闭增量构建,这个过程将是十分钟以上。
这个任务调度程序它在我们内部叫做 ci-task-runner,它的诞生是我们踩了 N 多坑的结果。在多个重要项目的生产环境稳定运行半年之后,我们决定将此作为团队第一个开源项目公布出来。
ci-task-runner 是一个标准 NodeJS 模块,它只做一件事情:观察文件或目录版本变更,启动对应处理程序。
因为简单,所以它非常灵活:
Github 主页:https://github.com/huanleguang/ci-task-runner
The text was updated successfully, but these errors were encountered: