不记得从什么时候起,“生态环境”这个词经常出现在人们耳边,而在IT行业中似乎出现频率更高——所有的巨头公司都在建设或运营自己的“生态环境”,要形成“闭环”。那么对前端开发来讲,是否也需要有一套自己的生态环境形成一个闭环呢?那前端开发的生态环境和闭环又应该是什么样的呢?

过去很长一段时间,我们都在探索适合自己团队的发展之路,建立大家共同认可的愿景和发展目标等。这时,首先要明确的就是,团队的追求和价值观是什么。最初,每次制定全年或季度的工作计划时,除和具体业务相关的工作外,还会出现提高工程质量、提高开发效率等这样的任务。随着时间推移,我们发现如果前端工程师的工作目标是让前端工程师们能更好地工作,那么就陷入了一个死循环,因为这个目标很难被具体化,也很难将前端工程师真正的价值体现在目标中。经过一段时间的探索,我们尝试从所参与的产品本身出发制定工作目标,这样“提高工程质量”、“提高开发效率”就变成了过程,产品的进步就代表前端工程师的工作产生了价值。

实践后发现这个方向是正确的,因为无论团队内部在做什么都只是手段和途径,而产品本身的改进证明目的达到了。进而我们开始尝试将整个过程系统化,于是就提到了开头所说的前端开发的生态环境和闭环。如果按照环境将前端工程师工作的平台进行划分,将会是开发环境、服务器和浏览器三个在物理上互相隔离的点,而通过一系列工具、平台和方法论,就能将这三个孤立的点串联起来,形成一个整体(如图1所示)。

图1   前端生态环境形成的闭环

通过这个闭环,特别是从浏览器回到开发环境这个环节,前端工程师会通过具体产品和终端用户进行频繁的信息交换,在最终的产品中进行信息收集,再将信息转化为指标或其他能够衡量产品质量的形式,以此指导工作方向。

打造前端研发生态环境

接下来,按阶段将整个过程落实到具体的工程实现上,最终的产出是一套完整的工具、平台和方法论。

从开发环境到服务器

开发环境是一切工作的开始,每一行代码都是从这里出发最终deliver给终端用户的,并不涉及到具体业务或产品。当团队人数增加、项目规模和数量开始膨胀时,很多日常的开发和发布操作就会占用工程师很多的时间和精力,而这些工作通常又是机械式重复的。为了解决效率问题,自动化是必然的方案。这个环节中大部分的问题抽象后都是工程问题,也就是通常所说的前端持续集成(CI)。合理的CI过程可以有效提高开发效率和工程质量,提供快速且可靠的持续交付能力。目前,豌豆实验室的前端CI过程如图2所示。

图2  豌豆实验室的前端CI过程

其中包含了以下环节:

  • 版本管理,保证代码安全和协同工作的效率;
  • on-save或pre-commit检查,包括lint和code style检查;
  • Code Review;
  • 自动化测试;
  • 自动化构建;
  • 自动化部署。

工程在开发环境进行简单的提交前检查,如静态分析和简单的测试,然后提交到代码托管服务,通过Code Review后合并入库,进行完整的自动测试,最后根据需要发布到测试或生产环境。

整个流程的核心工具是Grunt。Grunt是一个基于Node.js的任务管理和调度工具,最初是完全按照前端开发的需求打造的,但得益于其强大的扩展性,现在也可以被用于其他类型的工程。Grunt的核心是Gruntfile.js文件,其中预留了众多诸如测试、构建、部署等任务入口,可以在各个阶段中按需调用。

对于中小型团队来讲,合理利用开源项目和第三方服务可以有效降低在这个环节上的投入。同时,因为工程自动化要求同种工程的结构等都是相近的,这也是一个将对工程进行规范化的契机,通过Yeoman或类似的工具可以实现这个目的。

服务器到浏览器

经过前面提到的CI,工程就被发布到了线上服务器,可以分发给终端用户了。服务器在整个闭环中起到的是承上启下的作用,其中很多工作都是离前端工程师的传统认知比较远的内容,主要包括:

  • 负载均衡;
  • 静态资源管理;
  • CDN自动化管理;
  • Cache策略管理;
  • 线上服务性能指标监控;
  • 安全防护。

从传统的技术团队合作分工来看,这一部分内容通常是由运维工程师来完成的。但我们发现由于服务器和浏览器之间的信息交换的畅通和效率将会直接影响产品在某些方面的体验,所以其中某些部分也是可以被前端工程师纳入到工作内容当中的,或者是可以基于前端的需求进行调整和优化的,主要集中在加载速度和可靠性以及安全三个方面。

这个过程需要和运维团队紧密配合,要求对方提供统一、与业务无关且可编程的配置接口,将服务规范化。例如,某工程的静态资源在CDN上的过期规则,可在工程的配置文件中进行描述,在发布时自动通过CDN或CDN源站提供的API进行操作。

业务层的安全防护也应该在这个环节中考虑进来,例如统一的跨站脚本防御策略、API的CORS应用策略和CSP规则等,都应该由前端来驱动进行制定和实施。

浏览器到开发环境

浏览器是前端工程师的主场,大部分的工作最终都把浏览器当作运行环境,因此这个点也是最重要的。在这个点上主要包含以下工作内容:

  • 客户端性能监控;
  • 异常捕获与收集;
  • 用户行为跟踪与统计;
  • 用户反馈收集。

可以概括地分为工程数据和用户数据收集两大部分。工程数据是用来监控产品的性能指标和异常情况的,进而有针对性地进行性能调优和Bug修复,而产品数据则是用来分析用户的需求指导产品功能改进的。除了配套的统计工具外,也要能从这些数据当中转化有意义的信息,同时,以这个点为基础,不停地改进整个循环。

响应速度也是一个需要重点考量的目标,无论是线上产品的异常还是性能退化的发生,或者某个功能设计失误导致用户使用出现严重问题,都应该能在这个流程中快速反馈回来进行快速响应,将损失降到最低。同时,在正常的开发过程中,响应速度快也能够提高产品本身的迭代速度。

同样,在这个环节也有很多第三方服务可以使用,最常用的就是Google Analytics了,可以提供性能跟踪、用户行为统计、事件统计等常见的网站数据分析服务。除此之外,还可以使用SpeedCurve来对加载性能进行针对性的跟踪和分析,使用Roolba或Appfial服务来收集运行时异常。

以工具为基础,工程师就可以对产品最终运行的情况有更形象和具体的认知。例如,当我们对加载速度进行优化时,就可以看到点击率的上升或跳出率的下降,因此这些指标就可以坐为我们制定工作目标的标准。

闭环

到这里,一个完整的前端开发生态环境就形成了一个闭环。以此为基础,前端工程师只要将大部分精力放在最后一个环节,就可以快速地改进产品,让工作最终以产品本身为导向来进行。回过头来,总结一下在这个过程中的几个原则。

从前端开发的角度看问题

这个生态环境当中,很多内容都是和产品设计、运维等其他工作有交叉的,并不是说前端工程师要把更多相关的工作纳入进来,而是要能从自己的角度对同一个问题有不同的看法和解决方案,这样才能发挥出前端更贴近用户的优势。

其实这个研发闭环的打造过程没有任何的新内容,都是每个前端工程师日常工作的一部分,区别在于从系统化的角度将它们串在一起了。这个闭环中,最重要的是最后从浏览器回到开发环境的过程,但数据的收集和分析工作在不同的公司组织架构下可能是由其他角色来完成的,如数据挖掘工程师或者产品经理等。但我们相信,由于前端工程师的特殊工作性质,使其能够同时从工程和用户两个角度观察产品,那么也会有自己独特的解决问题的方式和途径。这个生态环境是为了能以产品为中心指导工作而进行的基础建设,本质上也只是一个工具,如何利用好它,需要整个团队进行长期的探索和磨合。

不重新发明轮子

对于团队来讲,快速、准确地解决问题,满足需求是唯一目标,因此当遇到问题时首先要仔细分析真实需求到底是什么。需求明确后,就涉及到具体的实现方案设计和技术选型等工程方面的决策,开源项目或者合适的第三方服务依然是首选,原因有三。首先,也是最重要的,投入产出比。在整个闭环的打造过程当中,会用到无数的工具和服务,其中每一个的复杂度都是非常高的,如果自己从零开发,时间成本、人力成本都将高到一个不可接受的状态。其次,开源项目和第三方服务通常比较专注,对所要解决的问题有更深刻的理解。例如,代码托管服务GitHub及相关的配套服务,显然其更专注在代码托管、团队协作方面的需求。最后,开源项目和第三方服务的扩展性和兼容性通常是有保障的,做为开源项目或第三方服务,为上下游其他工具和服务的接入提供良好的支持是基本的目标之一,保证了其在整个链路中的低耦合性和可替代性。当有更合适的解决方案时,可以方便地将其替换掉而不影响整个系统的稳定性。

将“人”的因素转化为“非人”的因素

“人"是最不可控的变量因素,无论是工程质量、发布流程,人工参与的操作都是最容易出问题的环节。因此,应该尽可能在整个过程中将更多人的因素转为非人的因素,机器化的流程就变得更可控和可靠。举一个具体的例子,Code Style是每个团队在成员数量开始增加时都要制定的第一个规范,但规范有了之后能否具体实施到每一行代码中、实施的效果怎么样,其实是取决于人——也就是每个成员个体,且这个执行情况是不可控的。这时我们就需要通过某种手段将其转为自动化的过程,也就是引入代码的静态检查,如JSLint或JSHint,自动化检查过程就将Code Style的执行情况转变成了非人的因素。自动化不只是提高生产效率的手段,同时也是保证质量的重要途径。

写在最后

很多团队都在探索前端未来的发展方向,我们也不例外。大家思考这个问题的思路似乎都是相似的,想要跨端——将前端拓展到Android、iOS等平台。有的团队是借助PhoneGap这种给WebView加壳的形式,也有的是通过Titanium Mobile或类似的解决方案,打包一个JavaScript Runtime,通过bridge来操作Native API甚至直接将JavaScript编译成某种目标语言。现在讨论前端,不加特殊说明的情况下是特指Web前端,而Web前端是被限定在特定的技术平台上的。上面提到的两种思路,本质上还是被限制在了Web前端自己的技术体系内。那么,如果抛开具体的技术实现来思考这个问题呢?

前端,应该是最接近用户的上层业务,工作内容是做UI,而User Interface绝不仅仅只是狭义的视觉上的界面,而是和Interface这个词的本意——接口,两个不同系统交接并通过它彼此作用的部分——一样,是两个系统进行信息交换的中间介质,而且信息本身是形式多样化的。两个系统,就是指用户和其所使用的具体产品。从这个角度看,将前端的业务范围拓展到其他平台是合情合理的,而且在这个层面上,任何平台上做前端开发都应该是有统一的价值观和方法论的。

前面提到的这个闭环,如果将所有的技术细节和实现方案全都隐去,进行进一步抽象,只留下需求,就会变成图3中的一个环形。

图3  抽象后的生态系统闭环

这个环中(其中生产环境对iOS和Android等客户端开发并不一定存在,所以是虚线)每一个环境的需求都是有普适意义的,也可以在其他平台上面尝试类似的工作方式。其中,运行环境到开发环境这一步,因为涉及到很多用户体验、数据收集和分析的相关工作,对前端的意义也显得格外重要。正是这一部分,使得前端工程师同其他工程师区别开来,也是前端工程师最能体现自己价值的地方——距离用户更近,能从不同的视角来思考和解决问题。而如何将所有终端都统一的内容抽象出来,结合产品形成前端统一的价值观和方法论,就是需要进一步探索的内容了。

最后,推荐一些开源项目和第三方服务,可以直接用来打造自己的前端研发生态环境:

  • JSHint,JavaScript代码检查工具;
  • Yeoman,工程初始化工具;
  • Grunt,任务调度和驱动工具;
  • Karma Runner,测试驱动工具;
  • Mocha,测试框架;
  • GitHub,著名的Git工程托管服务;
  • Travis CI,和GitHub整合的CI服务;
  • Circle CI,可以和GitHub或Jenkins整合的CI服务;
  • Codeship,能和GitHub或Jenkins整合的CI服务;
  • Google Analytics,数据收集和分析服务;
  • Speed Curve,网站性能统计和分析服务;
  • Roolba、Appfail,网站运行期异常收集和分析服务。

作者赵望野,豌豆实验室前端工程师,曾任豌豆荚2.0前端技术负责人,现任前端基础技术组负责人。