引用苏宁前端架构师的一个总结作为开篇
处在2015年这个时间段来看,前端生态已经进入了第三阶段。看上去好像已经走的挺远了,实则不然。如果再用人类历史上的三次工业革命来类比,前端 发展其实不过刚刚迈入了蒸汽机时代,开始逐步用工具来替代过往相当一部分的人肉作业,但是离电气时代的自动化流水线作业还有很长一段路要走。回顾一下 2015年前端的生态发展,我大致整理了几个我觉得比较有历史意义的事件。 按时间顺序:
css方面,postcss & cssnext先后高调走到台前。 观念的变化由于近几年前端的野蛮生长以及前端应用的多元化和复杂化,整个技术形态已经跟几年前纯做页面的时代完全迥异了。主要观念的变化总结来看在于一点,现在的前端开发面向的是web app而不是web page。 今天的前端开发模式跟传统的GUI软件(如C++、.NET开发的windows客户端)已经很接近了,而且由于现在前端领域为了解决日益复杂的web业 务需求及体量,越来越多的借鉴了传统客户端的开发经验,导致两者变得越来越趋同。再加上前端一些独特的特性(免安装、增量安装等),工程上的复杂度有过之 而无不及。前端如今已经脱离了茹毛饮血、刀耕火种的原始社会,开始步入了工业时代。 框架 & 类库的变化今年最火的框架/类库毫无疑问当属React了。React从2014年年中开始广泛受到开发者关注,但是真正开始在社区独领风骚还得归功于 2015年初React Native的发布。React Native的发布使得js统一三端(前端、后端、移动端)开发成为可能(现在这个时间点看可能还是过于理想,但是整体方向还是对的),这一针强心剂吸引 了大量开发者的眼球。笔者对此最大的感受就是,我在社区发表一篇react的入门教程级别的软文便可获得广泛关注及转发,相应的写angular源码剖析 的准干货大部分情况则是门可罗雀。 我们挑几个主流的框架来讲讲这一层的变化。 React & Redux React基本简介可以参考这篇文章React简介,这里不再赘述。这里挑几个核心特征简单来讲:
Redux则是目前react配套的Flux模式的各种实现(其实现在两者的关系越来越模糊了)中最火的一个,在此基础上它引入了函数式编程、单一
数据源、不可变数据、中间件等概念。一定程度来讲,redux是今年react生态甚至整个前端生态中影响最大的一个框架,它给整个前端技术栈引入了很多
新成员,尽管这些概念可能在其他领域已经有了广泛的应用。虽然它们是否会在大规模的应用实践中被广大开发者认可还需要再检验,但至少给我们带来了一些新的
思路。其中的单一数据源、不可变数据、中间件等思路目前来看还是非常有价值的,尤其是单一数据源跟不可变数据,很有可能在将来成为大型应用架构中的标配
(目前来看至少在应用中构建Store层在当前的前端架构中是势在必行的)。单一数据源就好比在前端构建了一个集中式数据库,所有的数据存取操作对象都是
它,不单如此它里面还实现了触发器,当有insert/update操作时它会对相应组件作rerender动作,这个在各组件之间有数据同步需求的场景
下就非常有用了。 在我看来,react的优势并不在组件化,组件化的实现方案多种多样。react的优势在于virtual dom及一个几乎构成闭环的强大生态,这归功于F家工程师强大的工程能力跟架构能力。virtual dom将应用表现层从浏览器这个基于dom的上下文中抽离出来,通过原生js对象模型的方式使得react具备在任何环境支撑上层表现的能力。上层的渲染 引擎可以是canvas、native、服务端甚至是桌面端,只要相应的端提供基于react组件的渲染能力,即可达到一套代码、或者只要很少的改动就能 移植到任一终端环境的效果,这个就非常夸张了。react从0.14版本之后便将react-dom抽出来变成一个独立的库,可见react的野心并不局 限于浏览器,相反从这点来看,react反而是受到了dom的掣肘。 Angular2 & Vue.js ng2跟ng1相比是一个完全革命性版本而不是升级版,它是一个为了迎合未来的标准及理念来设计的全新框架,而这些新的理念又无法通过改进 ng1.x的方式来实施,所以angular团队做了这么一个看似激进的决策,可以理解成重构已经无法满足需求只能重写了。ng2也采用纯组件化的开发思 路,任何单元对于它来说都是组件。同时,ng2里面也引入了一些全新的概念(对于前端而言)来提升框架的性能及设计,例如基于worker的数据检测机制 能大幅度提升渲染性能(对应实现是zone.js),基于响应式编程的新的编程模型能更大的改善编码体验(对应实现RxJS)。赶在2015年的尾 巴,ng2正式发布beta版,对于angular的这次自我革命是否能成功,还有待后续检验。另外原angular团队中出来的一个成员开发了一个类 ng2的框架aurelia,有相当的开发者认为它更配称为ng2,值得关注。 由于阿里在背后的技术实践及支持,Vue.js今年也开始得到越来越多的关注。vue相对于angular1.x的优势在于轻量、易用、更优异的性能及面向组件化的设计,目前发展态势也非常好,是移动端开发的一个重要技术选型之一。 标准 & 语言的变化现在回顾起来,2015年真的是很有意义的一年:这一年是Web的25岁生日,也是js的20岁生日。同时又是ES6标准落地的一年。ES6是迄今 为止ECMAScript标准最大的变革(如果不算上胎死腹中的ES4的话),带来了一系列令开发者兴奋的新特性。从目前es的进化速度来看,es后面应 该会变成一个个的feature发布而不是像以前那样大版本号的方式,所以现在官方也在推荐 ES+年份 这种叫法而不是 ES +版本。 ES2015(ES6) & ES2016(ES7) & TypeScript 6月中ES2015规范正式发布,从ES2015带来的这些革命性的新语法来看,JS从此具备了用于开发大型应用的语言的基本要素:原生的 mudule支持、原生的class关键字、更简洁的api及语法糖,更稳定的数据类型。而这些new features中,有几个我认为是会影响整个前端发展进程的:
关于ES2016的最重磅的消息莫过于11月初es标准委员会宣布将Object.observe从ES2016草案中移除了,尽管它已经是
stage2几乎已经是事实标准。官方给出的解释是,这3年的时间前端世界变化实在太大,社区已经有了一些更优秀简洁的实现了(polymer的
observe-js),而且React带来的immutable
object在社区的流行使得基于可变数据的Object.observe的处境变的尴尬,O.o再继续下去的意义不大了。
目前ES2015/ES2016都有了比较优秀的转译器支持(没错我说的是babel),但是也不是all features supported,尝新的过程中需要注意。 至于Typescript,你可以将它理解成加入了静态类型的js的超集。不过我对于这种转译型语言一直不感冒(包括快死掉的CoffeeScript),有兴趣同学自己去了解下吧。。 WebAssembly WebAssembly选择了跟ES2015在同一天发布,其项目领头人是大名鼎鼎的js之父Brendan Eich。WebAssembly旨在解决js作为解释性语言的先天性能缺陷,试图通过在浏览器底层加入编译机制从而提高js性能。这个事情跟当时V8做 的类似(有兴趣的同学可以去了解下JIT),V8也因此一跃成为世界上跑的最快的js引擎。但是由于js是弱类型的动态语言,V8很快就触碰到了性能优化 的天花板,因为很多场景下还是免不了recompile的过程。WebAssembly提供工具将各种语言转换成特定的字节码,浏览器直接面向字节码编译 程序。其实在此之前,firefox已经搞过asm.js做类似的事情,只不过WebAssembly的方案更激进。有人认为WebAssembly可能 是2016年最大的黑马,如果wa能发展起来,若干年后我们看js编写的应用会像现在看汇编语言写出的大型程序的感觉。WebAssembly项目目前由 苹果、谷歌、微软、Mozila四大浏览器厂商共同推进,还是非常值得期待的(写不下去了我决定回去翻开我那本落灰的编译原理。。)。 Web Components webcomponents规范起草于2013年,w3c标准委员会意图提供一种浏览器级别的组件化解决方案,通过浏览器的原生支持定义一种标准化 的组件开发方式。webcomponents提出之际引发了整个前端圈的躁动,大家似乎在跨框架的组件化方案上看到了曙光。但是前端这圈子发展实在太特么 快了,在当前这个时间点,webcomponents也遭遇到了跟Object.observe相似的尴尬处境。我们先来看看webcomponents 的几个核心特性:
其中1、4现在都能很容易的通过自动化的工程手段解决了(shadow dom对应的是scoped css),而自定义标签这种事情不论是React还是Angular这类组件框架都能轻松解决,那么我用你webcomponents的理由呢? 架构的变化2015年出现的新的技术及思路,影响最大的就是技术选型及架构了。我们可以从下面几点来看看它对前端架构上都有哪些影响。 组件化 React的风靡使得组件化的开发模式越来越被广大开发者关注。首先要肯定的是,组件化是一个非常值得去做的事情,它在工程上会大大提升项目的可维 护性及拓展性,同时会带来一些代码可复用的附加效果。但这里要强调的一点是,组件化的指导策略一定是分治(分而治之)而不是复用,分治的目的是为了使得组 件之间解耦跟正交,从而提高可维护性及多人协同开发效率。如果以复用为指导原则那么组件最后一定会发展到一个配置繁杂代码臃肿的状态。如果以组件的形态划 分,可以分为两个类型:基础控件和业务组件。基础控件不应包含业务逻辑不然达不到拿来即用的效果,因此它也会表现出可复用的价值,但是根本还是为了提高业 务组件的可维护性。至于业务组件,可复用的价值就很低了。
综合来看,我觉得工程上更具可行的全组件化方案应该是:细粒度的基础组件库 + 粗粒度的模板/组件。 工程化 工程化是近年前端提到最多的问题之一,而且个人认为是当前前端发展阶段最有价值的问题,也是前端开发通往工业化时代的必经之路。这里不赘述,有兴趣的同学看我前阵子整理的一篇文章前端工程化知识点回顾 应用架构层 MVVM & Flux MVVM想必大部分前端都耳熟能详了,代表框架是angular、vue、avalon。angular在1.2版本之后加入了
controllerAs语法,使得controller可以变成一个真正意义上的VM,angular整个架构也才真正能称之为严格的MVVM(之前只
能说是带有双向绑定的MVC/MVP)。
第一点第二点我并无异议。angular的脏值检测机制相对于其他mvvm框架的双向绑定实现方式确实不太优雅,同样有硬伤的还有失败的模块语法及过多过于复杂的概念。但是对于第三点,我有不同的看法。 业务数据层 Relay & falcor 这一层对大部分前端来说可能是比较新的概念,其实我们可以这样理解:在一个完整的应用中,业务数据层指的就是数据来源,在angular体系中可以等同于ngResource模块(准确来说应该是$http)。 新的编程范式函数式编程(FP) 函数式编程(functional programming)是近年比较火爆的一个编程范式,FP基于lambda演算,与以图灵机为基础的指令式编程(Java、C++)有着明显的差异。 lambda演算更关注输入输出,更符合自然行为场景,所以看上去更适合事件驱动的web体系,这点我也认同。但问题是,太多开发者看到redux那么火 爆就急着学redux用js去玩函数式,我觉得这个有待商榷。js作为一个以基于函数(scheme,父亲)跟基于对象(Self,母亲)的编程语言为蓝 本设计然后语法又靠近Java(隔壁老王)的“混血”语言,你非得用它去写函数式,是不是过于一厢情愿?尤其是在现在浏览器还不支持尾调用优化的情况下, 你让那激增的调用栈可如何是好,如果你确实钟情于函数式,可以去玩玩那些更functional的语言(Haskell、Clojure等),而不是从js入手。最近看到一个老外关于js 的函数式编程的看法,最后一句总结很精辟:Never forget that javascript hate you. 函数式响应型编程(FRP) 函数式响应型编程(functional reactive programming)不是一个新概念,但也不过是近两年才引入到前端领域的,代表类库就是ng2在用的rxjs。FRP关注的是事件及对应的数据流, 你可以把它看作是一个基于事件总线(event bus)的观察者模式,它主要适用于以GUI为核心的交互软件中。但FRP最大的困难之处在于,如果你想使用这样的编程范式,那么你的整个系统必须以 reactive为中心来规划。目前微软维护的ReactiveX项目已经有各种语言的实现版本,有兴趣的同学可以去了解下。 工具链的变化去年最主流的前端构建工具还是grunt&gulp,2015年随着react的崛起和web标准的快速推进,一切又有了新的变化。 webpack & browserify & jspm webpack跟browserify本质上都是module bundler,差异点在于webpack提供更强大的loader机制让其更变得更加灵活。当然,webpack的流行自然还是离不开背后的react 跟facebook(可见有个强大的干爹多么重要)。但是从现在HTTP/2标准的应用及实施进展来看,webpack/browserify这种基于 bundle的打包工具也面临着被历史车轮碾过的危机,相对的基于module loader的jspm反而更具前景(虽然现在使用前两者的开发者都多于jspm)。 PostCSS & cssnext PostCSS作为新一代的css处理器大有取Sass/Less而代之的趋势,Bootstrap v5也有着基于PostCSS去开发的计划。但从本质来讲它又不算一个处理器,它更像是一个插件平台,能通过配置各种插件从而实现预处理器跟后处理器的效果。 写在最后从前端的发展现状来看,未来理想的前端技术架构应该是每一层都是可组装的,框架这种重型组合的适用场景会越来越局限。原因在于各部件不可拆卸会增加
架构的升级代价同时会限制应用的灵活性。举个例子,我有一套面向pc端的后台管控平台的架构,view层采用angular开发,哪天我要迁移到移动端
来,angular性能不行啊,我换成vue就好了。哪天觉得ajax的写法太挫,把http层替换成fetch就好了。又有一天后端的GranphQL
平台搭好了,我把ngResource换成relay就OK了。 近年前端生态的野蛮发展影响最大的应该就是新产品的技术选型了,乱花迷人眼,我们很难设计出一套适应大部分场景、而且短时间内不会被淘汰的架构。前 端的变化太快通常会导致一些技术决策的反复,今天的最佳实践很可能明天就被视为反模式。难道最合适的态度是各种保留各种观望,以不变应万变?在这一点上即 使如我这般在技术上一向激进的人都有点畏手畏脚了。那句话怎么说的来着?从来没有哪个圈子像今天的前端一样混乱又欣欣向荣了。有人说2015年或许是大前 端时代的元年,目前看来,如果不是2015,那么它也一定会是2016年。 最后引用计子winter的一句话作为结语吧:
|