本文由Worktile产品研发部负责人徐海峰分享,也就是说,在过去的十几年里,前端工程逐渐进入了大家的视野,并且越来越多的公司开始关注前端工程。那么什么是前端工程呢?可以参考我前不久在知乎上的一个回答。什么是前端工程?这两年前端工程基本稳定下来了。每个公司都积累了自己的一套工程实践方法和工具。本文主要分享Worktile从2013年到2020年的前端工程,给大家介绍一下一家初创公司前端工程8年来的演变过程。一张简单的图回顾过去的8年:2013Worktile诞生回溯到2013年,我做服务器工程师的时候开始接触前端,第一次听说Hash路由:浏览器URL更改后整个页面没有刷新。那一年也是Worktile诞生的一年。对于一款团队协作平台SaaS产品,我们主要面对的是前端工程问题。即:前端框架选择。那时候,可供选择的框架并不多。Vue和React还没有出现。最后,我们选择了Angular.js作为前端开发框架。主要原因是:Angular.js适合有WebApp体验的SPA单页应用双向数据绑定,数据驱动开发,避免手动操作Dom。选择AngularJS后,我将从开发、构建、部署三个方面来说明当时的工程化水平。开发:第三方依赖包手动拷贝维护,按照框架功能划分目录结构,所有状态存储在$rootScope;构建:通过手写uglify-js2压缩合并一个Node脚本,不使用构建工具;deployment:我记得印象特别深刻的是deployment。CEO每发布一个版本,都需要通过BeyondCompare一个一个的比对文件,然后我们一起看修改的内容,决定是否同步更新到服务器,然后重启服务。现在回头看2013年,感觉那个时候的前端工程基本处于原始社会。当时的CEO和CTO都是开发工程师。一共只有4个人,1个前端还负责UI设计。这基本上是一个新成立的创业公司形式,产品跑得很快,需要工程化。2014年到2015年,LessChat诞生,直到2014-2015年,因为要做中国版的Slack,LessChat(后来在Lesschat的基础上,增加了任务、网盘、日历模块,就是现在的Worktile),因为它一个新产品,根据以往的经验,肯定要重新考虑整个前端的架构设计。我们也从开发、构建、部署三个方面来解释一下当时的工程:开发:开始介绍包管理工具Bower,按模块划分目录结构,模块基本上就是一个字段的意思,避免说一个组件和一个函数分散在不同的文件夹中,同时前端引入数据层Service作为管理状态,不再所有状态都存在$rootScope中,其余引入。棉绒工具;构建:先后引入了Grunt、Gulp构建工具;部署:使用中转机Shell脚本一键部署,不再使用BeyondCompare对比上传。2016Webpack+模块化2016年最大的变化是构建工具和包管理工具的转变,从Gulp到Webpack,从Bower到npm。其实工具转型的本质原因是:模块化,前端开始重视模块化开发了。那么Webpack无疑是前端模块化的一个转折点。同时Webpack支持CommonJS规范,前端可以使用NPM生态,Bower自然被淘汰。在前端没有引入模块化之前,为了避免命名冲突,一般采用命名空间和自执行函数的方式。引入模块化之后,命名冲突的问题就迎刃而解了。不再需要自己封装一个自执行函数,那么除了解决命名冲突之外,引入模块化带来的价值远不止于此。方便依赖管理:无需手动维护脚本引入的顺序问题。便于性能优化:可方便集成Webpack打包工具,按需加载,更细粒度的模块划分和动态加载,提高可维护性:按照模块划分,每个文件职责单一,组织结构清晰且合理,可维护性大大提高。有利于代码复用:代码复用不是模块化的最终目的,只是一个附带的价值。使用模块化和组件化最重要的意义就是分而治之(Divideandconquer),可以说中大型前端项目终于变得可维护了,这也是前端工程的意义所在。如果前端不变得越来越重要越来越重,就不会有前端工程化。因为我们使用的是Angular.js框架,所以基本上可以说不支持模块化。通过下图你可以感受到Angular.js的模块化。这里简单介绍一下模块化的发展:随着2009年Node.js的诞生,CommonJS进入了大家的视野。CommonJS是JavaScript的静态模块化规范,适用于Node.js但不适用于浏览器环境。前端资源除了JS还包括CSS、图片等,同时CommonJS是同步阻塞加载,无法实现异步按需加载。为了让浏览器环境也能使用模块化,后来诞生了AMD/CMD规范。无论是CommonJS还是AMD/CMD,都是语言规范缺失时代的产物。应用场景单一,模块无法跨环境运行,构建工具不统一,不同规格的模块无法混用,模块复用性不高。.直到2015年ES6Module一统天下,前端模块化终于稳定下来。2017前后端分离2017年,Worktile的前端工程主要做了以下两件事:全站模块化(2016年引入模块化后,历史模块的迁移需要时间,基本上需要一个一年依次完成所有迁移)前后端到端存储分离(2017年之前,Worktile的前后端都存储在一个仓库中。虽然是SPA单页应用,HTML由服务器呈现)。该项目是前端的全静态项目。部署后,不能强制缓存HTML文件。Nginx需要配置try_files指向index.html。HTML模板是服务器端渲染。服务端渲染HTML模板模式下有两种子模式:第一种是HTML模板由服务端团队负责。这种模式的工程需要解决前端搭建完成后如何通知服务端更新的问题。资源问题;第二个子模式是大前端。前端团队使用Node.js渲染HTML模板,甚至和前端项目维护在同一个仓库。2018年是前端工程元年2018年,我认为是Worktile开始前端工程的元年。我们一直在使用Angular。否认Angular.js是一个已经被淘汰的前端框架,所以我当时就大胆升级到Angular,主要有以下几个原因:2018年Worktile产品计划为8.0,高配置的项目管理模块,以及复杂度急剧上升我们想开始构建我们自己的组件库。基于Angular.js,似乎没有太多的热情和动力继续使用Angular.js。也会面临招工难的问题,人才培养也是如此。Angular框架正式发布后,逐渐趋于稳定,可以投入生产。至于为什么我们没有选择Vue和React,主要是因为我们更符合Angular的哲学。大而全,解决了我们所有的痛点。人少,没精力折腾。基于以上原因,我开始翻阅Angular的官网Documentation,初步跑通了Angular+Angular.js混合方案,然后做了一个技术分享。大家比较热情,就直接介绍了Angular,也因为Angular介绍了TypeScript和RxJS。除了升级Angular,我们在2018年还做了以下重大工程改进:构建了一个内部组件库:ngx-tethys(对于我们当时的团队规模和业务压力,我们无法想象一个前端和后端一个10人左右的开发团队实际构建了一个内部组件库);LESS迁移到SASS,bootstrap3升级到bootstrap4(sinkhole的样式也需要补上,幸好这些都踩过了);使用RxJS作为状态管理,封装了一个适合我们业务的轻量级状态管理库。更多细节请参考Angular真的需要状态管理吗?升级Angular混合应用也会遇到一些问题:首先是性能问题。AngularZone的集成。.js和Angular路由还是会存在一些冲突,同步路由等问题,需要你不断尝试,可能会写出一些你现在永远也看不懂的代码。Angular.js使用的是ui-router,不是官方的路由;Angular.js和Angular之间的服务和组件虽然可以相互调用,但是弹出模态框的机制是不一样的。Angular.js用的是ui-bootstrap,而Angular用的是CDK,所以层级冲突的问题也很棘手。forkbootstrap的组件库修改源码,解决模态框冲突问题。回顾2018年,因为技术升级和新业务确实带来了很大的压力,我们的很多技术选型都增加了大家的负担,但是这一切都是非常值得的,因为技术升级给整个前端带来了巨大的冲击团队。随着动力和能力的提升,很多小伙伴在这一年可以熟练掌握TypeScript,也具备了独立构建组件的能力。也许他们以前连想都不敢想。这么复杂的系统升级和迁移都通过了,还有什么不能通过的呢?(永远记得前端刚开始用各种TSany)2019PingCode诞生2019年,我们开始做研发管理工具(PingCode于2020年10月独立),这是又一个新的跨代产品。有人说,技术变革往往与产品息息相关。在过去的8年里,Worktile基本上经历了四次大的产品变更,前端工程也基本随着这四次产品变更而发生了变化。今年以来,开发、建设、部署等几个方面都取得了突破性变化。开发开发,除了继续选择Angular框架外,最重要的是引入微前端。之前也分享过:ToB企业级应用使用Angular搭建微前端架构自研ngx-planet微前端框架,所有子产品独立入库,独立部署因为独立入库,所以需要构建业务组件库,提取通用业务组件,开始重视单元测试。基础库被迫写单元测试,过去的组件库开始补充测试。引入wt-cronus工具,一键克隆升级,安装,启动多个应用,解决多个存储管理难的问题最后再详细介绍一下当时为什么采用微前端。2019年建设前后引入了jenkins进行持续集成。由于前端使用的是微前端,构建时使用了基于AngularCLI的angular-builders扩展构建器,可以利用AngularCLI带来的便利,可以灵活扩展Webpack的配置适配微前端的框架.部署与构建相同。2019年前后端使用jenkins持续部署,所有服务使用Docker容器部署。同时使用kubernetes进行容器部署、扩展和管理,完全实现自动化运维。除了规范和流程的开发、构建和部署方面的改进外,2019年还引入了《Commit Message 提交规范》、《分支管理规范》(类似于GitFlow)和《Code Review》。引入CommitMessage规范,可以为类库项目自动生成Changelog,更好的跟踪应用的Git提交记录,同时与PingCodeAgile用户故事进行双向关联;分支管理配合自动化部署和发布流程,使版本管理和自动化部署更加规范化和流程化;一开始引入CodeReview最担心的问题就是会不会增加大家的工作量。从实际结果来看,CodeReview的好处远远大于坏处,不仅大家的代码质量提高了,阅读和理解别人代码的能力也提高了。为什么选择微前端?任何技术选择的核心原因仍然取决于业务需求。如果公司遇到的工程问题不用引入微前端就可以解决,那么最好不要引入微前端。那为什么我们使用微前端而不是Monorepo?在架构上,主要有以下几点:兼容遗留系统:刚开始做PingCode的时候,我打算把它和Worktile集成。Worktile是一个巨大的Angular+Angular.js混合应用程序。首先,编译打包速度已经很慢了。第二,很多工程的东西不规范,修改起来很麻烦。采用新的架构设计会更容易(后来在产品上线前,最终选择了独立,没有集成Worktile);多团队多子产品:最初包括4个子产品,每个子产品由一个独立的Scrum团队负责,预计未来会有更多的团队做更多的子产品。截至目前,已有包括内测、线下子产品在内的8个子产品,无论是团队管理还是仓库管理独立分离都是理想的;应用市场:在产品规划的前期,我们的目标是打造一个类似于jira的丰富的应用市场,也就是说除了加载官方子产品外,还会在应用市场加载嵌入式应用。甚至在未来,第三方也会开发嵌入式应用。目前,“待办事项”和“甘特图”这两个嵌入式应用程序是我们的内部应用程序。当然,选择微前端后虽然解决了很多痛点,但也带来了一系列的工程问题:独立存储后,还需要构建业务组件库。业务组件库越来越大,打包发布速度却越来越慢?不支持真正意义上的自主开发。本地开发需要启动Portal等多个服务。本地开发需要手动刷新页面。不支持LiveReload和HMR。整个系统过于复杂,理解整体架构变得更加困难。没有样式隔离,子应用产品部署也需要部署Portal。遇到问题并不可怕。你可以一一解决。如果一开始你选择了Monorepo,相信你还会遇到其他的工程问题。2020年标准化与流程。伴随着微前端带来的一系列工程问题,我们进入了2020年,2020年的主要目的就是解决这一系列的问题:真正意义上的子产品独立开发,不需要多次启动Portal等服务在真正独立开发之后,LiveReload和HMR也逐渐支持风格隔离方案的确定和实施。每个子产品完全独立部署。内部devkit工具集完善,通过wpmrelease和wpmpublish简化了发布流程。我们创建了一个组件库和一个业务组件库,所以组件库的文档还比较粗糙。2020年的另一项重要任务是完善文档。为了完善文档,我们开发了一个文档生成工具Docgeni——Angular开箱即用的组件库文档生成工具(稍后会正式开源),基于Docgeni,我们对文档的文档进行了迁移重构组件库和业务组件库。测试覆盖率组件库和业务组件库的测试覆盖率提升至70%。因为之前欠债太多,我们对服务端的测试覆盖率要求一直高于前端。服务器端常见子产品的单元测试覆盖率基本都在80%以上。补充测试是一个持久的工程问题,它也定义了公司的测试覆盖率指标。DevelopmentSpecifications&ProcessSystems2020年,除了上面这些,我觉得是Worktile开始标准化和流程化的一年。WTC(技术委员会)发布了16个开发规范和16个流程体系。2021和未来,是Worktile过去8年的工程之路。作为一家初创公司,其实并不容易,因为没有太多的资源投入。我们一直在保证产品高速迭代的同时完善前端工程,不管是组件库。或者说开发工具是业务团队所有前端成员共同努力的结果。跟大厂比起来,我们还是差了一大截,但是对于前端团队不到20人的公司来说,已经很不容易了。2021年才刚刚开始,我们会继续把前端工程做的更好,一步步提升自己。2021年和未来,我想我们会继续从两个方面发力:务实和平台化。对于实用主义:过去,我们构建了组件库、微前端、Docgeni和Devkit等基础设施。未来我们需要不断改进,不断改进测试和文档,第二是引入更多的自动化工具来简化我们的工作流程。最后就是开源回馈社区。过去我们开源了微前端ngx-planet,以后我们会开源更多我们的前端工具和类库来回馈社区,包括我写的这篇博客。也希望更多了解Worktile前端工程的人,能对同样是初创企业的你有所参考和帮助。平台化:在务实的基础上,如果精力和资源允许,会引入一些平台化的工具,比如:前端监控平台,灰度发布系统等。最后,见证了Worktile的前端工程化步伐一步步到现在。分享我们的心路历程需要勇气。没去过大厂,对做前端工程的优秀公司不是很清楚。什么是状态?如果您对此有什么想法,欢迎与我们分享(尤其是国内使用Angular框架的公司)。最后打个广告:我们正在做PingCode,一款比Jira还好用的研发管理工具,欢迎大家注册学习!智能研发管理工具PingCode-官网
