6月30日举行的第39期百度技术沙龙活动中,百度前端工程师、F.I.S项目技术负责人张云龙分享了“F.I.S 2.0 全新的百度前端解决方案”。在演讲中,张云龙介绍了F.I.S的产生背景和架构、前端开发需要满足的最小规则集合、F.I.S如何满足这些需求、前端开发过程中的一些最佳实践,以及F.I.S三种工作模式(release/install/server)的原理。
会后,InfoQ就F.I.S对张云龙进行了采访。
InfoQ:请为我们介绍一下F.I.S,它究竟是什么?
张云龙:F.I.S,全称Front-end Integrated Solution,即前端集成解决方案。
我们发现,不管哪个前端团队,不管他们的产品有多大差别,在发展的过程中总会渐渐形成一套配合自己产品开发的【项目规范】+【前端框架】+【模板框架】+【自动化工具】+【辅助开发工具】,这些技术需求的总和就是F.I.S。
经过一年半的努力,我们和众多产品线前端团队共同探索出一套前端集成解决方案。我们相信,在支持了百度30多条产品线,覆盖从PC到移动端的众多项目之后,我们所总结的F.I.S系统是具有普适性的,它能够快速应用到绝大多数公司的前端团队中,并有效的提升其生产力水平。F.I.S在百度孕育的过程中的经历和思考,以及F.I.S系统演变等“思想产物”对其他公司的前端团队来说,在寻找提升前端生产力水平解决方案的道路上也有许多可借鉴之处。
InfoQ:F.I.S项目是如何诞生的?是什么原因促使百度成立F.I.S团队,开发并着手进行推广?
张云龙:在F.I.S出现之前,百度的每个前端团队都或多或少有这样一套东西,然而产品线与产品线之间由于采用的技术基础不同,没办法互通有无。而且每个新人加入团队后,只有需要熟悉自己门派的规范、工具和流程后才能上手项目。另外,每个团队都需要投入一定的人力来维护自己的系统。这些工作的成本相当高昂。
而随着团队规模增大,很多产品线之前设计的系统在大团队下都会出现不同程度的问题。尤其是当性能优化摆上项目议程的时候,面对多人团队,想要较平滑的对页面性能进行优化几乎是不可能的!
为了解决这些问题,前端研发部顺势成立了F.I.S团队,希望可以找到满足这些技术需求的通用解决方案,能够整合前端开发资源,对系统进行持续的平滑的性能优化,并提升前端团队生产力水平。
当时,我们面对的是大型互联网公司内部五花八门的前端开发模式,以及各种神秘莫测的自动化工具。直到现在,我都觉得能在这样大规模的互联网公司内统一前端开发是一件非常了不起的成就。当我们用了一年半的时间,几乎完成百度前端团队统一使用F.I.S 之后,才将过去所做的一切沉淀下来,希望能够为业界贡献一些新的思路和想法。而F.I.S这个产品也作为前端工业化的最佳实践开源出来。
InfoQ:为何选择Node.js作为F.I.S的基础?
张云龙:事实上,最开始在百度内部使用的F.I.S是用PHP实现的。由于当时设计思路的局限,我们认为,既然后端模板是Smarty,那就必然需要PHP环境,也就理所当然应该使用PHP作为自动化和辅助开发工具的技术选型。这样一个想当然的决定,使得我们经历了非常漫长且痛苦的开发过程,毕竟PHP不是为了做这样的事而设计的。
直到今年年初我们才意识到,虽然模板需要PHP环境运行,但并不意味着自动化工具必须用PHP开发!多么浅显的道理,但是,又是多么痛苦的领悟。很快我们把注意力转向了Node.js。它对前端工程师有着非常强的亲和力,有各种基于Node.js的压缩、优化、校验工具,有着极高的运行性能,有npm这样强大的包管理工具……简直就是为自动化和辅助开发工具量身定做的平台嘛!因此我们毫不犹豫的选择用Node.js重写F.I.S。而且在这次重构中,我们认清了F.I.S的本质、理顺了F.I.S要专注的事情和F.I.S系统的层次关系。最终,F.I.S变成了现在大家看到的样子。
InfoQ:F.I.S如何帮助开发者提升工作效率?
张云龙:首先强调一点,F.I.S系统包含四个非常重要的部分:【前端组件化框架】+【后端模板框架】+【自动化工具】+【辅助开发工具】。诚然,自动化工具是F.I.S的重要组成部分,但如果把F.I.S单纯当作类似Grunt的自动化工具就太片面了。因此,对于F.I.S如何提升前端开发效率,可以从这几个方面讲起:
F.I.S提供了一套高效的前端项目编译系统:该系统可以很方便地组织前端编译工具,对项目进行优化、测试、校验、打包等处理。
F.I.S的自动化工具扩展了前端语言的三种能力:资源定位、内容嵌入、依赖声明。资源定位能力可以帮助系统隔离开发环境和部署环境之间的变化;内容嵌入功能可以帮助工程师解决资源的初等拆分合并问题;依赖声明可以构建大型的组件化系统。这些工作量都会因为接入F.I.S而省掉。
F.I.S的自动化工具会扫描整个项目的资源生成一张资源表。这张表可以与前后端框架配合,精确地按需加载资源,平滑地优化网站性能,甚至可以利用监控数据来自动优化网站性能,从而实现自适应的网站系统。
F.I.S的资源表支持命名空间特性:可以将一个大系统拆成几个子系统来维护,子系统之间没有依赖关系,开发、提测互不影响,从而提升团队的并行能力。
F.I.S的辅助开发工具可以解决工程师的本地调试、数据模拟等问题,解耦前端代码对后端程序的依赖,提升前后端团队的并行开发能力。
F.I.S的辅助开发工具还提供了自动部署多台联调或测试机的功能,节省了工程师联调和提测的时间。
百度内部使用的F.I.S系统是有固定技术选型搭配的,因此内部项目初始团队几乎没有选型的成本,F.I.S把开发中的点点滴滴就想进去了。
InfoQ:F.I.S中带有文件编译,以及若干优化手段,那么如何评价通过F.I.S产出项目的性能?
张云龙:百度内部使用F.I.S的产品线都有自己的前后端性能统计数据,百度的Web前端研发部也有性能小组来跟踪各产品线的性能指标,这些都会成为衡量F.I.S收益的重要手段。
性能收益是比较容易衡量的,但F.I.S的另一项收益——生产力提升——比较难以量化。目前还只是从产品线工程师的口碑,以及一些直观的工作量减少上得到反馈。相信在各大互联网公司前端团队的类似项目中,都有遇到这类情况。虽然目前还不能以数据的形式反映F.I.S在生产力提升上的成效,但从迄今为止F.I.S在百度内部的普及程度以及产品线使用之后项目的迭代速度来看,它确实带来了很多收益。
InfoQ:请为我们介绍一下F.I.S中的静态资源优化,与传统打包的差异吧。
张云龙:“雅虎14条优化原则”教导我们要减少HTTP请求,传统的静态资源打包策略采用的是简单直观的“文件合并”方式。这种方式在小团队、实验性或内部系统项目上运作的还好,因为它毕竟非常直观。但随着团队规模的壮大,这种策略非但不能优化前端性能,反倒会带来前端性能的恶化。比如Facebook在Velocity China 2010的讲座议题《静态网页资源的管理和优化》中提到的一个传统资源打包都会遇到的尴尬问题:
出现这一问题的另一典型场景是换肤和国际化。传统资源合并策略难以满足这样的需求。
最开始,F.I.S的实现思路是针对不同产品线提供不同的打包工具。很快我们就发现,F.I.S团队陷入了不断创造各种版本的打包工具的泥潭,维护成本非常高。这迫使我们寻求通用的打包解决方案。基于资源表的静态资源管理系统就是这样诞生的。
使用资源表有很多好处:首先,打包成了资源的备份,可以非常方便地控制页面是否输出打包后的结果,线上页面很容易通过query将页面切换为输出零散的资源,以便工程师定位线上问题。其次,基于资源表的静态资源管理系统,在产品线的模板框架层实现了静态资源的调度,使得F.I.S团队不用针对每个产品线写一套独特的打包工具。而资源调度策略可以非常灵活,我们后来还实现了资源的异步加载等功能,极大提升了页面首次渲染的速度。近期,我们还在几个产品线做了静态资源调度统计的实验,通过统计数据来生成最优的打包算法,让网站性能随用户访问而自适应优化。
InfoQ:在F.I.S中,如何管理框架、插件等资源的,开发者如何添加插件?
张云龙:F.I.S提供了install命令,可以用来获取各种前端开发资源,比如示例、配置、组件、基础库、框架、甚至前端开发素材等。
我们后续会努力经营好这个资源和F.I.S的install这个入口,为用户提供优秀的、逐版本的前端开发资源。
F.I.S的自动化工具/辅助开发系统完全插件化,我们利用npm来扩展F.I.S。而F.I.S的所有插件与F.I.S核心是分离的。如果用户想在项目中使用Coffee Script、LESS、Markdown等语言来开发页面,那么只要在F.I.S安装目录的同级安装这些插件,F.I.S就能自动加载它们。F.I.S提供了11个扩展点,包括编译扩展(6个)、打包扩展(4个)和命令行扩展(1个)。所以大家看到F.I.S的GitHub项目上只有一个fis.js文件,请不要以为F.I.S项目是未完成的,因为那是我们整个系统插件化的结果啊。
InfoQ:你认为F.I.S最主要的亮点是什么?
张云龙:【语言能力扩展】、【基于表的静态资源管理系统】与【前端资源聚合】。我觉得这是F.I.S系统最大的三个亮点。
我们做了这么久的前端集成解决方案,才总结到这样一个结论:前端领域语言只要扩展了资源定位、内容嵌入和依赖声明三种能力,就可以实现绝大多数前端开发需求。有些前端自动化工具采用目录规范来替代资源定位能力,采用开发规范来替代依赖声明能力。这样做固然可行,但大大限制了其解决方案的适用范围。毕竟每个公司、每个团队都有着自己不同的开发理念,我们曾经在“开发规范”这条路上走了很久,回头看看才发现,规范都是浮云。依靠比规范更小的原子规则就可以组合形成规范,它们才是前端自动化工具的“尺规”。
基于表的静态资源管理系统设计是我们发现的另一块瑰宝。有了它,我们才能实现平滑的性能优化,自适应的网站系统,方便的线上问题定位手段,根据不同浏览器和国家地区投送不同的静态资源。而且资源表只是一种数据结构,与平台无关,很容易让fis平滑地接入到不同类型后端的系统中。
F.I.S解决了以上开发问题之后,开始向着前端资源聚合迈进。我们希望能将业界优秀的工具、代码、技术等资源聚合起来形成生态系统,让前端工程师最平等快捷的获取前端开发资源,找到所求。所以我们在插件系统设计、资源获取上下了很多功夫,虽然最后的结果看起来很简单,但那是为了让大家能用最低的学习和使用成本获得最大的收益。
InfoQ:F.I.S起自2011年,那么在过去一年多的时间里,它是如何演进的?
张云龙:F.I.S系统至今已演化了三代。
第一代(2011年末~2012年中): F.I.S团队刚组建,我们还没有认清F.I.S的本质,以为编译就是一切。所以在参考了公司内几个比较大型产品线的前端构建工具之后,我们把其中几个运行的比较好的系统杂糅了一下,得到了第一代F.I.S——项目代号Gaea——并交付百度云相册团队试用。说真的,第一代F.I.S系统实现的很糟糕,给人一种摇摇欲坠的感觉,好像一不小心就会导致崩溃一样。它大量使用了目录规范,尽管这些规范都是来自大产品线经验的总结,但还是很难被新人接受。就这样,一代F.I.S在百度呱呱坠地,或许不那么闪耀,但起码有了一个开始。
第二代(2012年中~2013年初):虽然一开始比较艰难,但好在靠着产品线同事的大力支持和团队每个人骨子里的那种倔强精神,我们挺过了F.I.S最艰难的时期。后来,随着F.I.S的不断铺开,我们开始面对大团队、大规模产品线的开发需求,同时也增加了对移动开发的支持。这一代F.I.S项目的内部代号是Oak,其功能处于快速增长期。我们很善于使用编译工具来解决前端开发中遇到的各种问题,与此同时也衍生出了很多针对特定终端的开发模式,包括PC、Mobile、WebApp甚至RIA等。也正是在这个时期,我们设计出了基于表的静态资源管理系统,而且F.I.S的后台界面也变得相当华丽,整个F.I.S系统的代码已增至8万行!但是很快我们意识到,肆意的使用编译能力,会导致系统产生巨大的黑盒效应。虽然F.I.S系统产出的结果非常高效,但普通工程师对其原理不甚了解,代码难于调试。而F.I.S团队在维护编译工具的路上也越陷越深,自顾不暇。
第三代(2013年3月至今):由于2013年初所暴露的种种问题,F.I.S项目的问题开始进入不收敛时期,团队的几个负责人也认识到了问题的严重性,因此组织了几次闭门会议。这几次会议中,我们很严肃的思考了F.I.S的过去与未来,找到了问题的症结,并对关于F.I.S是什么、F.I.S的本质和理念是什么的问题做了很深入的思考。我们重新检查了F.I.S的代码,在将近10万行代码中找到解决前端开发问题的最基本的三条规则,并确定了以资源表为核心的静态资源管理系统设计理念,放弃华丽的后台界面改为命令行交互。最终我们决定,用Node.js重构F.I.S,完成对F.I.S的减法升级!这就是大家现在看到的F.I.S了。
F.I.S不是某个风和日丽的下午我们一拍脑门想象出来的,所有现在大家看到的结果,都经历了大规模大团队实战的考验。开源以后,希望业界可以看到我们曾经为解决这些棘手问题而沉淀下来的结果,相信这些经验是很值得借鉴的。
InfoQ:在下一阶段,F.I.S将会向什么方向前进?
张云龙:后续F.I.S会朝着【前端开发资源聚合】和【高性能前端架构设计】两个方向迈进,我们会不断的开源在公司内部孵化出来的前后端框架、组件、交互体验示例等资源,并对前端性能优化、开发体验、自动化工具、前端项目测试等领域做进一步的探索和研究。我们希望借助F.I.S平台可以不断整合公司内外前端资源,输出优雅高性能的解决方案,以此来提升前端工业生产力水平。
InfoQ:F.I.S目前的推广情况如何?下一步F.I.S团队对于它的推广有什么打算?
张云龙:推广才刚刚开始,比起毫无意义的广告和论战,我们团队更注重实际的产出。后续我们还会继续开放出我们在前端工业化领域所做的探索,并不断的将这些经验化作程序可描述的结果通过F.I.S平台输出给大家,我相信这就是最好的推广方式。
InfoQ:对于行业中,前端工业化整体情况做一些点评和展望吧。
张云龙:也许是我比较关注这一领域吧,我发现这两年各大互联网公司纷纷开始打造自己的集成解决方案,甚至有专门针对这一领域的岗位招聘,相信大家都已对这个方向的未来心照不宣了。五年前,前端团队能用上或者实现一个前端库来解决常见DOM操作问题已经非常不错了;三年前,前端团队能拥有一套工具来自动压缩代码就已经能解决很多开发问题了;而如今,我们要考虑的更多:框架,工具,库,辅助开发,组件化,性能优化、多终端、国际化、团队协作……新时代的前端集成解决方案是严肃思考的产物, 它能成为前端团队开发的重要利器之一。从过去到现在,从JS库到工具再到集成解决方案,相信前端人在提升生产力水平的道路上会披荆斩棘,不断前进!
张云龙是来自百度公司Web前端研发部,前端集成解决方案小组的技术负责人,目前负责F.I.S项目,读者可以关注他的微博:http://weibo.com/fouber/。