【第3072期】利用前端基础设施为前端应用打造稳健且高效率的开发体验
前言
本文讨论了前端基础设施的概念和重要性,介绍了前端基础设施团队在统一技术栈、规范开发流程、优化性能等方面的工作,以及如何通过工具和流程提高开发效率和产品质量。同时,还分享了一些实际应用的经验和工具,如 Lighthouse CI、SonarQube、Docker 等,以帮助小型团队或个人开发者构建自己的前端基础设施。今日前端早读课文章由 @莫力全 Kyle Mo 授权分享。
正文从这开始~~
什么是 Frontend Infrastructure(Infra)?
提到前端网页开发,可能很多人联想到的都是 UI 页面切图、动画特效,甚至认为前端开发者的工作内容「离不开页面」。但其实前端开发是一个非常广的领域,同样身作为前端工程师,每个人专注开发的领域可能都不一样,所打造出的技能树也长成不同的形状。而我自己更感兴趣的是前端开发基础建设(infrastructure)相关的议题,那到底哪些技术属于基础建设的范畴呢?
其实在相当久之前,我写过一篇关于 Frontend Infra 的简短文章,但当时自己只是觉得这个前端领域中的分支看起来很酷,并没有太深入的理解,在实际加入企业中的 Web Frontend Infra Team 研究了很多有趣的主题之后,我想针对这个题目我有了不同的体悟,因此决定结合过去的经验,重新整理一下我对于 Frontend Infra 的认知和想法。
首先我们先看看 ChatGPT 对于 Frontend Infrastructure 的理解是什么(现在很多工程师对于 AI 的回答甚至都超越了对人的信任了🤣):
可以发现因为 Frontend Infra 并没有一个明确的名词定义,所以其实各种前端相关的技术都可以被归类到其中,比如效能优化、CI/CD、Bundler…… 等等都可以算是 Frontend Infra 的范畴,基本上它的具体内容以及定义会根据组织、团队与个人的需求和目标而有所不同。
虽然这么说,社区中对于这个术语,还是有一个较为普遍的定义:
Frontend Infra 这个词通常用来描述为了提升「开发效率」和「产品质量」而导入的一套系统、或流程,并且通常包括一些关于如何使用这些工具和系统的最佳实践或标准。
这个定义了各位读者可以先回顾一下,我们在最后会再回顾一次。
回到上面 ChatGPT 的回答,我们可以发现对于「大规模」的组织来说,前端基础设施是非常重要的,这是为什么呢?
管理多个前端项目
对于大型组织来说,同时有多个前端项目要开发与维护是很常见的事,除了给客户(有可能是 2C,也有可能是 2B)使用的项目之外,也可能会给企业人员使用的内部系统,这时面对要同时管理多个前端项目的情况,采用方式会比较有效率呢?
我们当然可以个别看待每一个项目,从头打造每一个代码库、采用不同的技术栈,并个别发展该项目所属的标准(如测试指南)与基础建设(如 CI/CD Pipeline)。不过采用这种方式你可能会发现一个问题:
我们违反了 DRY(不要重复自己)原则,一直在做重复的事情。
对于这种情况,有些企业会选择独立出一个专门的团队来协助打造前端的基础建设,这个团队的目标通常会包含以下主题:
1. Boilerplate (Generator)
通常在项目的最初阶段会需要选择适合这个项目需求的技术栈,例如要使用 React 还是 Vue ?是否需要采用 SSR 的框架,例如 Next.js 或 Nuxt.js?在决定要使用的技术后,我们可以选择从头开始建立开发的环境,例如一个一个安装需要使用的组件,从头开始编写 linting 的规则配置,不过为了节省时间,我们也可以选择使用别人写好的 boilerplate template,例如 create-react-appVue Cli ,基本上只需在 terminal 下几行指令就可以快速搭建出架构蛮完整的项目。不过这些由官方提供的模板有时并不能完全符合企业所想要复用的功能,因此有些公司会选择现在自己的模板,来达成更定制化的需求。
使用模板的好处是可以更快速的建立项目环境,不过它仍旧有一些成本在,比如维护模板的成本、依赖模板的情况下比较难导入新技术(比如原本的模版已经整合了 Redux 来处理状态管理) ,这个时候如果想要更换其他的状态管理组件会需要花费额外的工夫)…… 等等,在使用相应模板之前也需要仔细评估一下。
2. Sharing Code
当我们在开发上积累比较多经验后,应该会理解共享代码以避免重复编写相同逻辑的概念,也就是所谓的共享代码。而共享代码其实有非常多种方式,小至把共用的 util 函数拆掉分到其他文件,大至如果要在不同的项目间共享代码时,可以考虑使用 public 或 private 的 npm 来管理,又或者在 monorepo 架构下可以分割成独立的 package 来提供 repo 中的其他不同项目使用。
当然几乎任何方法的背后都带有风险成本,如果只有一个项目,要修改代码相当方便,不用怕去影响到其他项目,不过如果是在不同的项目间共用代码,就必须用更严格的标准保证程序代码的品质,同时让程序更加具备弹性与可重用性,在测试上也必须变的更加强健。因此就算开发同样的功能,要思考重用性就会让开发与维护的成本增加许多。另外版本控制也是一个难题,在不是使用 monorepo 而是 private npm 的情况下,要如何确保每个项目都能跟到共享代码最新的版本且不能造成毁灭性的 breaking change,是个耗废心力的问题。
3. Design System
现代的前端开发都是以组件化开发为主,你一定曾经遇到过在不同的项目中需要使用功能和样式都差不多的组件(比如 button),这时候你可能会需要「共享设计」,而 Design System 就是常见的解决方案。
而前端开发者可以进一步依照设计系统实现出组件库,可以依照需求使用 Vue、React,又或者是你有跨框架共用的需求,也可以考虑使用 Web Component 来实现。这其实也是一种「分享代码」的方式,所以同样会具有第二点共享代码的优缺点点,不过它也会带来一些额外的限制,比如更严格的「设计」准则、比较缺失弹性的样式设计风格…… 等等。
4. Unified CI/CD Infra
项目在完成开发后通常会需要经过构建和测试来验证代码的质量与正确性,在经过严格的检验后才能部署上线,而通常这些步骤都会贯穿 CI/CD pipeline 自动化。在拥有多个项目的情况下,对于每个项目独立建立一个 CI/CD 管道当然是一个选择(目前待过的公司也都是这样用的),不过也有另一种方式是建立一个统一的 CI/CD 基础设施,让各个项目的开发者可以不用花太多工在建立管道上,而由 Infra 团队负责这些管道的建立和维护。
采用统一基础设施的风险大概就是可靠性了,统一管理管道实际上也带出单点故障的风险,万一今天基础设施炸掉了可能会阻碍每个项目开发或发布的流程。
除了上述 One Pipeline 的方式,也有的团队让每个项目拥有各自的 CI/CD 管道,全部遵循一致的流程与标准,确保所有前端项目都有高品质、一致的开发、测试和部署流程。
5. Deploying & Serving
经过 CI/CD 的验证后网站最终就可以上线啦!我们当然不希望自己租一个主机再把网站相关文件搬过去上线(可以,只是很麻烦),更何况还要设置 CDN 等等机制,目前来说最方便的方式应该就是寻求云端解决方案了(Cloud),这种方式的风险无疑就是云端服务商的可靠性,万一今天云端服务商出事了,连带的可能会影响到底下千千万个服务。
6. Monitoring
在前端项目中,我们经常会结合像 Sentry、Google Analytics、Google Search Console 等工具来追踪各种指标,如错误消息、用户行为与监控流量、Web Vitals 等。这样的监控系统可以帮助我们深入了解网站的运行状态,并发现网站需要改进或修改的地方,提供一个实际为基础方法来优化我们的应用。
在没有 Frontend Infra Team 协助打造工具或制定共同标准的情况下,项目初期看似可以快速推进,不过长远来看行进却是缓慢的,当公司日益成熟导致项目越来越多的情况下,会出现一直重复造轮子的问题,代码的品质也会随着随着项目数量变多而产生分歧。
有了 Frontend Infra 以后,长期来看会推进的比较快,代码的品质也会比较好,不过缺点是需要比较多的人力与成本来完成这些事情,因此一般来说规模扩大的企业比较适合采用独立于前端基础设施团队的模式。
Web Frontend Infra Team 参与经验分享
很幸运的,我之前刚好有参与 Web Frontend Infra 团队的经验,这个章节就来回顾一下我在 FE Infra Team 的日子都做了些什么事,跟大多数人普遍认为的前端工程师的职责有各种各样的区别。
(此章节的照片皆经过后制或模拟,非当事图片。)
我身处的 Web Frontend Infra Team 的主要职责就如上图所示,主要有以下几点:
统一各个前端项目的技术栈
制定各项目间统一的开发标准
开发各个项目可以共享的 Packages
提升前端应用的可观测性
在这些首要目标指引下,我参与期间,团队专注于几个特定主题的讨论:
接下来的段落简要介绍了自己参与的主题研究。
Lighthouse CI
关于 LHCI 这个主题我其实在去年 MOPCON 年会就作为一个主题较详细的分享过了。通过自架 API Server 与 Database,我们把每个项目每次跑 LHCI 的结果都储存起来,如此一来除了可以透过 LHCI 提供的仪表板观察特定项目在特定时间区间的 Lighthouse 检测趋势之外,也能够比较不同次检测的结果,将 Diff 后的信息像上图一样透过 GitHub API 以 PR 评论的形式回馈给项目的开发人员,让 Lighthouse CI 可以成为前端项目的故障守门员,尽量确保不让可能会造成应用故障大打折扣的代码被合并到 Repo 中。
SonarQube
SonarQube 是一个代码检测以及质量管理平台,Web Infra Team 花了一些时间收集了想要应用在 JS/TS 项目上的规则集合,把 SonarQube 加入到项目的 CI 流程里,在发布 Pull Request 时会帮我们检测 PR 改动的文件是不是有一些潜在的 bug、漏洞、安全问题、Code Smell,我们可以设定这几项问题的总数如果超过某个数字就禁止 PR 被合并,需要生成符合规则集合的写法才通过,通过这种方式,我们可以避免推上一些品质不佳且跟不上团队编码标准不契合的代码。除此之外,SonarQube 还能帮忙记录测试覆盖率,在 CI 流程中我们会先执行 Test 并得出测试覆盖率的报告,将覆盖率上传给 SonarQube,它除了会帮助我们在平台上记录,也会在 PR 评论中显示该 PR「有改动到的文件」的测试覆盖率,我们同样做了一个限制,如果 Changed Files 的测试覆盖率没有超过 80%,该 PR 没办法合并,通过这种方式规范团队成员养成写测试的习惯。
自定义 ESLint 配置
创建自己定制化的 ESLint 配置其实并不困难,Wen Infra Team 有自己实践给所有前端项目 Extend 的自定义配置,这个配置除了包含 NextJS 和 React TS 等常见的配置外,主要还包含了我们在 SonarQube 平台上制定出这种规则集合的规则,希望利用这种方式,及早在 Lint 阶段就检查出一些可能会导致 SonarQube CI 报错导致 PR 没有办法被合并的可能性,这样可以进一步提升团队的开发效率。
在搜集 SonarQube 规则对应 ESLint 的规则的时候,我们发现很多规则是 ESLint 官方的规则没有涵盖到的,当然社区中很多人开发了对应 SonarQube 的 ESLint Config,但总有一些规则没有被覆盖到了,面对这种情况我们可能得选择自己实现 ESLint 的规则,要自己实现规则需要对 AST(抽象语法树)有基本的理解,这会是比较困难的部分。
举个例子来说,如果要写一个限制代码库里面不能出现 console.log
的规则,大概会如下:
module.exports = {
rules: {
"no-console-log": {
create: function(context) {
return {
CallExpression: function(node) {
if (node.callee.object.name === 'console' && node.callee.property.name === 'log') {
context.report(node, 'Do not use console.log()');
}
}
};
}
}
}
};
当然这个规则早就被 ESLint 官方配置涵盖了,核心主要是表达如果有定制化的规则,都有机会自己实现喔!
Generator
通过上一节提到的模板。我们可以发现 Infra Team 其实导入了很多工具和规范,如果每个项目都手动导入的话想必会非常耗时耗力,如果有一个项目生成器可以轻松通过 CLI 指令就建立出一个包含 Infra Team 规范的各种工具的必要配置文档的项目的话,可以减少项目启动的成本。因为在大型公司中建立新的项目是相当常见的一件事,这个生成器实际上发挥相当相当作用很大的。
Monitoring
前面有提到过提升应用的可观测性也是 Web Infra Team 的一个重要目标,因此 Infra Team 有建立了一个 Grafana 的 Dashboard,以视觉化的方式处理每个项目的相关状况,例如近期 PR 的测试覆盖率、近期 PR 违反 SonarQube 规则的数量与种类,同时在违反的数量过多时会发出警报通过 Slack 通知…… 等等,Infra Team 可以以一个中心监管者的角度观察每一个项目的情况,也可以提醒更多情况不好的团队要加强注意。当然 Dashboard 还可以放入更多的信息,例如 Web Vitals 各项指标与 Error 相关的信息…… 等等,都是可以尝试的方向。
DAST For Comply With DevSecOps
这个问题之前也有写过一篇介绍文章,主要是团队希望可以遵循 DevSecOps 的精神。DevSecOps 是一种观念或者说是一种实践方法,这个词是由 Development、Security 和 Operations 三个词组合而成的。DevSecOps 的目标是在软件开发生命周期的早期就整合安全性,以实现更安全的产品和流程。
如果我们可以导入 DevSecOps 的精神,在产品生命周期的各个阶段执行对应的安全性检测,就可以更快的获得反馈,也可以避免有漏洞的应用被部署到生产环境中。
因为整个产品的开发周期其实会需要不同的角色去协作,所以我们先拉回身作为开发者最直接可以影响的 CI/CD Pipeline。
如果要贯彻 DevSecOps 的话,理想的前端项目 CI/CD 管道应该会是下面这个样子:
白色为未知的流程,红色则为安全相关的步骤
而 Infra 团队研究的动态应用程序安全测试(DAST)则选择在部署到 Staging 环境后进行检测,使用的是 ZAP 这个开源工具,扫描后可以得到一份安全报告,团队成员报告可以针对去处理项目中潜在的安全漏洞。
ZAP 扫描报告
那如果是小项目或者小团队,可以导入 Frontend Infra 吗?
针对这个问题,我们同样先看看 ChatGPT 会另外:
针对这个问题,它的回答想法相当相近的。根据前面段落的说明,不可否认的是大型的组织与团队对于基础设施的需求一定是强烈比较的,但现在我们再次回顾前面提到的文章段前端基础设施的普遍认知:
Frontend Infra 这个词通常用来描述为了提升「开发效率」和「产品质量」而导入的一套系统、或流程,并且通常包括一些关于如何使用这些工具和系统的最佳实践或标准。
重点就在于「开发效率」与「产品质量」这两个要素,我认为只要符合这两个规范,任何尝试都可以被算在 Frontend Infra 的范畴里。
「开发效率」这一点很直觉,例如导入 Hot Module Replacement(HMR)或者做设计系统都可以提升开发效率,而关于「产品质量」,我觉得可以再进一步解读为「代码质量」与「产品」品质”,像 SonarQube、ESLint 等工具都可以帮助我们提升项目代码质量,而像效能优化、应用监控则可以提升产品质量。
当然对于小型团队或者个人开发者来说,自己动手做前端项目的基础设施建设会需要很大的成本,但其实现在很多现成的服务或工具让打造自己的前端项目的基础设施变得更加容易。有关注 Vercel 这间公司(它就是开发 Next.js 这个框架的公司)它在前阵子的会议上提出了 Frontend Cloud 这个名词,其实概念就是希望能够简化开发者构建基础建设的负担。
当我前阵子正好有机会帮朋友的一个小型前端项目建立基础建设时,我迅速分享了一下我导入了哪些事情。
执行标准
关于统一编码标准,选择的还是最熟为人知的 Prettier + ESLint 并搭配 husky 在 pre-commit 阶段触发,有趣的是透过 lint-staged 我们只可以对 staged(即已经 git add 的)文件进行操作,通过定制化配置可以指定针对不同副档名称的文件想要进行何种操作。
依赖管理
关于项目中的组件管理,我们是使用 Renovate 这个工具,它可以定期自动化的帮助我们发 Pull Request 更新 package.json 有用到的 dependencies 与 devDependency 的依赖关系,避免项目中的依赖组件长期不更新造成版本后面过多的问题,未来如果要一次升级会比较麻烦,也很容易遇到重大变化。Renovate 其实不仅支持 JavaScript,它还支持其他程序语言的组件管理,例如 Golang、Java、Python… 等等,它还提供非常丰富的 config 可以设置,例如指定每过多久要检查一次有没有可以升版本的组件并自动发 PR、或者指定只升级补丁版本或者只升级补丁跟小版本而不升级大版本… 等等都可以做到了,有兴趣的话可以再自行查看官方文件提供的设置。
使用 Renovate 后对于我们的改变是过往我们可能在 package.json 中的组件版本是使用以下的格式:
^xxx
(当组件有新的次要版本时,补丁版本将自动安装新版本)~xxx
(当组件有新的补丁版本时会自动安装新版本)
但是这样就会每次安装都有可能用到不同版本的组件,不知不觉间就让应用出现不预期错误的经验不在少数。原本不使用 pin 版本的写法就是担心组件的更新频率会过低,但是有了 Renovate 后再配置完整的 CI 工作流程,如果自动化升级组件的 PR CI Pipeline 是有通过的,我们可以更有信心的认为这次升版不会造成应用坏掉,这使得组件管理这件事变得更加完整轻松明显。
预览网址
预览 URL 可以在每次发 PR 或者在 PR 中有新的提交时都会自动部署一个版本并提供 URL 给进行代码审查的工程师或者 QA 工程师测试,我认为这是一个大幅可以优化开发流程的工具。
之前在 Infra Team 其实也尝试过制作过 Preview URL,但后来发现这个功能其实牵涉到很多复杂的流程,当时光制作一个 POC 就花了不少功夫。在这个 Side Project 中,我们选择使用 Vercel 提供的 Preview URL 功能,除了为每个 PR 部署一个测试版本之外,共同协作者还能在预览版上留言给予回馈,这无疑让工程师与设计师、QA 工程师的协作多了一层便利性。
而通过 Vercel 的预览 URL 功能也应证了刚才提到的前端云概念,该平台确实让导入前端基础设施的流程进一步简化。
Vercel 的预览网址还有让协作者一起留言讨论的功能
开发工具
在这个项目中有加入了一些可以协助开发又不会增加 production bundle size 的工具,例如可以观察不同页面 bundle size 组成的 bundle analyzer、找出不必要重新渲染的 Why Did You Render、画出项目依赖 dependencies graph 的 madge…… 等等,挑选适当的辅助工具可以增加团队的开发效率和质量。
但如果不考虑团队需求胡乱地添加工具而不考虑其用途或与现有工具的兼容性可能会导致开发环境混乱、学习曲线加长,甚至引入不必要的错误。过多或冗长的工具不仅可能增加设置和维护的复杂性,还可能占据团队的焦点,导致生产效率下降,因此在导入任何工具之前都建议先三思喔!
持续集成 / 持续交付管道
前端基础设施的 CI/CD Pipeline 具有重要的价值,主要包含「快速迭代」、「质量保证」、「降低风险」、「自动化」…… 等等优势,所以在这个 Side Project 中,我花了很多时间在思考如何优化 CI/CD Pipeline 的流程与效率。
Docker 镜像大小优化
Docker Image 的大小会直接影响 Pipeline 的构建时间与部署时间,甚至还会影响储存与网路的资源储备,所以我们希望尽可能优化 Dockerfile 的结构与减少构建的镜像大小。
这个项目是一个 Next.js 开发的应用,最初版本的 Dockerfile 是最简单的写法,但在本地构建镜像后发现镜像大小是不可思议的 3.4 GB😰,后来版本透过多阶段构建将镜像大小缩小到 871 MB,虽然进步不少的,但我总觉得对于一个开始开发不久的项目来说还是有点过度大,后来发现 Next.js 已经推出了 Output Tracing 这个方案,可以更近一步减少 Image Size 到 216 MB (以上 Image Size 都是本地构建后的大小,实际在 CI/CD 工作流构建出来的大小通常会再小一些)。我想除了 Next.js 以外,各种框架应该都有针对优化图像大小的特殊方式,建议大家可以去研究看看。
GitHub Actions Cache & Artifact
每个 CI 提供商都有自己独特的功能和限制,建议大家花点时间了解自己使用服务的相关信息。
如果你跟我一樣习惯使用 GitHub Actions,一定對 Cache 與 Artifacts 不陌生,这两者者都提供了储存和取回資料的功能,但他们的使用情境和特性有所不同。
Artifacts 更偏向于「结果的儲存与共享」,它保存的是 workflow 产生的重要文件,例如 build 的 bundle size 报告、Lighthoue CI 检测結果的文件… 等等。
Artifact 用來儲存重要文件
Cache 更偏向于「加速 workflow」,它保存的是可能在多次工作流之間重复使用的文件或資料,例如 npm install 后产生的 node_modules,如果我們发现 package.json 跟 lock file 沒有改动,可以合理推断并沒有新的组件被安裝或更新,这時候可以重用快取的组件,就不需要再跑一次 install。
指定 cache key,如果 cache hit 就不需要重跑 yarn install
然而 GitHub Actions 针对不同方案的使用者,对于 Cache 与 Artifact 都有对应的使用限制。
以这个 Side Project 來說,它是一個免費方案的 Public Repository,对于 Cache 与 Artifacts 的限制如下:
Cache:一个 Repo 的大小限制是 10GB,如果 7 天都没有被命中到的 Cache 就会被清除。
Artifact:一个 Repo 仅存 2GB,无论有没有被使用,在 90 天后都会自动清除。
免费帐号公共存储库的缓存与工件的限制
了解这些限制其实很重要,因为如果是在公司里面导入这些都是跟金钱成本有关的事情,如果当前的放弃不能满足团队的需求,可能就需要考虑花费更多的金钱来升级方案。
因为 GHA 的缓存是用分支与标识符来作识别的,所以,还是假设今天我有一个分支,你也有一个分支,将我们的锁文件内容提取一样,获得相应的缓存密钥也一样,但会因为在不同的分支而有两个 Cache Item,而我的分支不能使用你的分支的快取,反之亦然。
在这个项目中大约有 15-20 位协作者,在多个高频发 PR 的情况下,缓存可能很快就会超过大小限制,也因为是用分支作识别,所以很多快取其时在 PR 被合并分支被删除后就不会被利用了,但是合并规则还是需要 7 天后才会被清除,很明显有很多除存空间被浪费了。为了避免太快超过 Cache 的大小限制,我们在思考没有办法可以自己删除用不到的快取。
虽然 GitHub 有提供可以手动删除缓存的管理页面
但身为工程师,可以自动化的事情为什么要手动做呢?通过 GitHub Actions 与 GitHub API 并指定 PR Close 事件要触发就可以轻松实现自动化清理用不到的快取用量超过 Size Limit 啰!
Bundle Size Diffing
虽然已经导入了 Bundle Analyzer 可以观察 Next.js 应用的 bundle chunks 状况,但我想大多数人不会想到没就去看 bundle 的状况,等到哪天发现 bundle 变得异常肥大,通常也查不出一切到底是从哪里开始变了调😂我们在 CI 中加入 bundle size diff 的流程并显示在 PR 评论上,可以看到 PR 反转 bundle size 的波动,未来如果出现问题也方便比较痕迹。
而加入这个其实步骤不需要什么努力,因为在 CI 中本来就需要执行下一个构建,我们只需要把构建后的纯文字信息存到 artifact 就可以在未来用来进行比对。
Knip
虽然 ESLint 已经可以抓出很多语法错误,但它的主要架构仅限于单一文件系统的检查,它不具备检查整个项目系统的能力。
例如,程序代码中可能有这么一行:export const myVar = true;
。ESLint 将文件以单独的方式处理,所以它不知道 myVar 是否在其他地方被使用。而 Knip 恰恰派上用场,它能够对整个代码库进行检查,查找同时使用导出、文件和依赖项,这可以帮助提升项目的可维护性和性能。
我们选择把 Knip 这个工具绑到 CI/CD 流程中,在每周一次的发布后去执行检测,除了复盘这个 Sprint 的程序代码质量,也可以决定下个 Sprint 是否要排进相关的 Refactor。
开发流程优化
大多数 CI Provider 在执行工作流程时都可以获取 PR 或 Repository 相关的信息,例如 PR 标题、PR 编号、标签…… 等等。虽然这些信息第一眼看起来可能没什么用,但它们可能比你想要的还有价值。
我的经验是,有了这些 PR 相关的元数据,我们其实可以再配置 GitHub API,我们其实可以做到非常多的事情,就像上面提过的 Lighthouse CI Diffing、Bundle Size Diffing,因为需要保存每次检测的情况,我们可以选择使用这些元数据唯一的标识符以方便我们管理资源。
再举一个有趣的例子,我在帮忙建立这个项目的基础建设时,发现后面的协作者对于 PR Title 的写法都遵守规范,例如是 feature 写 feat: xxx
,是修 bug 就写 fix: xxx
,但对于 label 的使用大家习惯不太一样,有些人习惯上好上满,有些人则放上任何的标签。我自己在开发上是相当习惯放标签的,因为可以方便未来做过滤与分类。但当然我分类觉得上标签只是一个很小的事情,我不希望针对这么小事让协作者产生负担。所以我想到如果大家很遵守 PR title 规范,那我应该可以根据 PR title 去自动帮 PR 加上标签,于是我透过在 GitHub Actions 中写一点 Node.js 脚本就完成了这件事。(后来才发现原来之前就有人想到了同样的事情,而且已经写了更完整的自定义操作🤣)
前面提到的这个例子是想要分享的,我觉得 CI/CD Pipeline 其实充满了很多可以提升开发体验或流程的可能性,只要想得到机会就可以去做得到,这就前往各位发挥想力玩玩看啦!
可观测性
过去讲到可观察性,大多数人联想到的还是后端的系统日益出现这样的需求,近年来前端可观察性也逐渐受到重视。
在前端可观察性的全局中,通常会观察以下几个重要的面向:
Logging:Logging 是收集应用程序运行时的详细信息,比如用户行为、系统错误等。这些日志可以帮助开发者了解应用程序的运行状态和行为。
Tracing:Tracing 是跟踪请求的一个生命周期。例如,跟踪一次 API 请求从发送到接收到响应的整个过程,这有助于定位性能瓶颈和错误。
Metrics:Metrics 是以统计数据的形式来关注应用程序的性能和健康状态,如页面加载时间、错误率等。
Web Vitals:LCP、FIP、CLS 等对前端应用来说非常重要的用户体验指标。
错误:监控前端应用的各种错误、错误发生的时间、装置…… 等等。
以往不同种类的数据采集往往需要分散在不同的平台上,例如 Web Vitals 穿透 Lighthouse、Error 通过 Sentry,这对于应用的监控来说其实非常不方便。依托很多平台都推出了全栈的可观测性解决方案,让跨越前后端的各种信息都可以在同一个平台上被观测。
在这个 Side Project 中,团队目前仍在探索不同平台的优缺点,因此还没有确定最终要导入哪个平台,目前的候选有 New Relic 、 Grafana Faro 、Sentry ,有兴趣的读者都可以自行去探索看看喔!
看上去很零碎杂乱……
虽然在这个项目导入的东西看起来非常零碎,但如果我们把开发流程转化成流程图的话
透过流程图,我们可以很清楚的理解在项目中不同的开发阶段会触发哪些流程,团队也可以更方便的在每一步中的讨论,是否有多余或缺失的流程可以修改去。因此我蛮推荐大家可以针对前端应用的开发流程画出一份基本的流程图喔!
针对 FE Infra,还能导入什么?
任何东西。你想获得的技术或工具都有机会。
但是除了要尽量符合刚才提到的提升「开发效率」或者「产品品质」以外,还有更重要的一件事:
如果架构设计去掉了实际业务需求,那就是在瞎忙。调整软体架构必须深入理解需求,参与需求讨论,并透彻理解需求背后的业务本质。
Frontend Infra 的本质也是软件架构设计,因此在导入任何工具、流程之前,不妨先思考一下目前的项目是否有这个需求,毕竟每一个导入团队的事情对于成员来说都是认知增加负担,并不是看到的什么东西很潮很酷就可以一次导入到专案中。
想法总结
前端开发者的分类与角色多样性
前端老实说其实是一个很广泛的领域,即使职称都是前端工程师,每个人聚焦与钻研的方向又不太一样。以我自己的观察可以说,前端开发者又大略分为几种类型:
产品开发人员,专注于复杂的接口应用开发,我想大部分的接口开发者都会属于此类
专精于动画、互动设计(Canva、3D)的前端工程师(例如业界有名的版块设计的产品就有非常多复杂的动画效果)
Tooling Infra Developer:这些类型的 FE 开发人员的职责就比较聚焦于本文讨论的 FE Infra,以工具、制定基准来提升开发体验与产品质量。
除了前端本身的分类造成需要的技能树不同之外,随着近年技术的发展,前端开发者也需要培养许多过往跟前端开发似乎没那么相关的技能,例如简单的 Server Side 开发、CI/CD、Serverless … 等等,我们可以看出现今的前端开发者的角色多样性在逐步增加的。
前端基础设施跟团队文化相关
处理前端基础设施相关的任务时,要记住不仅仅只是导入技术、工具并修改开发流程,这是一件跟团队文化相关的事情。
当我们导入新的工具或流程时,不仅仅是技术层面的改变,更重要的是,每增加一个工具都会增加团队成员的认知复杂度,会直接影响团队成员的模式行为。因此,建立一个能够接纳并适应变化的团队文化,让团队成员了解导入任何工具、流程背后的意义与要解决的问题是什么,对于发展前端基础设施至关重要。
FE Infra 与 DevOps 的关联
FE Infra 与 DevOps 两者其实很明显有相关之处,它们共同的目标是提升软件开发流程的效率与质量。我们可以将 FE Infra 视为 DevOps 这个文化与方法在论前沿领域的实践中,两者紧密结合,共同优化开发流程。
理解需求,无需过度导入
前面提过「如果架构设计去掉了实际业务需求,那就是在瞎忙。」
在前端项目想要导入任何基础建设的时候,可以先思考一下是否有这个需求?如果有的话导入这个工具或流程后可以费尽心思的解决我们的问题吗?团队文化是否适合?成本是否可以承受?
在经过盘思考和初步验证之前导入任何东西,更有机会达到预期的价值。
关于本文
作者:@莫力全 Kyle Mo
原文:https://oldmo860617.medium.com/ 成為前端建築師吧 - 透過 - frontend-infra - 為前端應用打造穩健且高效率的開發體驗 - 21566b5c95d3
这期前端早读课
对你有帮助,帮” 赞 “一下,
期待下一期,帮” 在看” 一下 。