写点什么

解读 2015 之前端篇:工业时代 野蛮发展

  • 2015-12-29
  • 本文字数:7578 字

    阅读完需:约 25 分钟

编者按:2015 年,整个 IT 技术领域发生了许多深刻而又复杂的变化,InfoQ 策划了“解读 2015 ”年终技术盘点系列文章,希望能够给读者清晰地梳理出技术领域在这一年的发展变化,回顾过去,继续前行。

引用苏宁前端架构师徐飞的一个总结作为开篇:

编程技术及生态发展的三个阶段

  • 最初的时候人们忙着补全各种 API,代表着他们拥有的东西还很匮乏,需要在语言跟基础设施上继续完善
  • 然后就开始各种模式,标志他们做的东西逐渐变大变复杂,需要更好的组织了
  • 然后就是各类分层 MVC,MVP,MVVM 之类,可视化开发,自动化测试,团队协同系统等等,说明重视生产效率了,也就是所谓工程化

处在 2015 年这个时间段来看,前端生态已经进入了第三阶段。看上去好像已经走的挺远了,实则不然。如果再用人类历史上的三次工业革命来类比,前端发展其实不过刚刚迈入了蒸汽机时代,开始逐步用工具来替代过往相当一部分的人肉作业,但是离电气时代的自动化流水线作业还有很长一段路要走。回顾一下 2015 年前端的生态发展,我大致整理了几个我觉得比较有历史意义的事件。

按时间顺序:

  • 年初 React Native 的发布,引领 React 正式走上历史舞台。
  • 3 月 angular2.0 第一个预览版发布
  • 5 月 http/2.0 标准正式发布,同月 iojs 与 nodejs 合并。
  • 6 月 ES6 和 WebAssembly 落地
  • 7 月 迄今为止 React 生态圈影响最大的 Flux 实现 redux 发布 1.0 版本
  • 8 月 Facebook 公开了在 React 上应用 GraphQL 的 relay 框架的技术预览版
  • 9 月 React Native for Andriod 发布
  • 11 月伊始,ES 标准委员会宣布将历时 3 年研究的 Object.observe 从草案中移除,尽管它原本已经是 stage2,几乎已经是 ES7 的 事实标准。双十一刚一结束,阿里手淘团队发布了名为 无线电商动态化解决方案的 Weex,也有人给了它一个更具象的名字,vue native。
  • 12 月,赶在 2015 的尾巴,aurelia 和 angular2 先后发布 beta 版。

css 方面,postcss & cssnext 先后高调走到台前。

观念的变化

由于近几年前端的野蛮生长以及前端应用的多元化和复杂化,整个技术形态已经跟几年前纯做页面的时代完全迥异了。主要观念的变化总结来看在于一点,现在的前端开发面向的是 web app 而不是 web page。今天的前端开发模式跟传统的 GUI 软件 (如 C++、.NET 开发的 Windows 客户端) 已经很接近了,而且由于现在前端领域为了解决日益复杂 的 web 业务需求及体量,越来越多的借鉴了传统客户端的开发经验,导致两者变得越来越趋同。再加上前端一些独特的特性 (免安装、增量安装等),工程上的复杂度有过之而无不及。前端如今已经脱离了茹毛饮血、刀耕火种的原始社会,开始步入了工业时代。

框架 & 类库的变化

今年最火的框架 / 类库毫无疑问当属 React 了。React 从 2014 年年中开始广泛受到开发者关注,但是真正开始在社区独领风骚还得归功于 2015 年初 React Native 的发布。React Native 的发布使得 js 统一三端 (前端、后端、移动端) 开发成为可能 (现在这个时间点看可能还是过于理想,但是整体方向还是对的),这一针强心剂吸引 了大量开发者的眼球。

我们挑几个主流的框架来讲讲这一层的变化。

React & Redux

React 可以参考这篇文章以及深入浅出React 专栏,这里不再赘述。

Redux 则是目前 react 配套的 Flux 模式的各种实现中最火的一个,在此基础上它引入了函数式编程、单一数据源、不可变数据、中间件等概念。一定程度来讲,Redux 是今年 React 生态甚至整个前端生态中影响最大的一个框架,它给整个前端技术栈引入了很多新成员,尽管这些概念可能在其他领域已经有了广泛的应用。虽然它们是否会在大规模的应用实践中被广大开发者认可还需要再检验,但至少给我们带来了一些新的思路。

在我看来,React 的优势并不在组件化,React 的优势在于 virtual dom 及一个几乎构成闭环的强大生态,这归功于 Facebook 工程师强大的工程能力跟架构能力。virtual dom 将应用表现层从浏览器这个基于 dom 的上下文中抽离出来,通过原生 js 对象模型的方式使得 React 具备在任何环境支撑上层表现的能力。上层的渲染引擎可以是 canvas、native、服务端甚至是桌面端,只要相应的端提供基于 React 组件的渲染能力,即可达到一套代码、或者只要很少的改动就能移植到任一终端环境的效果,这个就非常夸张了。React 从 0.14 版本之后便将 react-dom 抽出来变成一个独立的库,可见 React 的野心并不局限于浏览器,相反从这点来看,React 反而是受到了 dom 的掣肘。

Angular2 & Vue.js

Angular 2 因为不向下兼容引起了社区的争议,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 中,有几个我认为是会影响整个前端发展进程的:

  1. Module & Module Loader
    ES2015 中加入的原生模块机制支持可谓是意义最重大的 feature 了,且不说目前市面上五花八门的 module/loader 库,各种不同实现机制互不兼容也就罢了 (其实这也是非常大的问题),关键是那些模块定义 / 装载语法都丑到爆炸,但是这也是无奈之举,在没有语言级别的支持下,js 只能做到这一步,正所谓巧妇难为无米之炊。ES2016 中的 Module 机制借鉴自 CommonJS,同时又提供了更优雅的关键字及语法 (虽然也存在一些问题)。遗憾的是同样有重大价值的 Module Loader 在 2014 年底从 ES2015 草案中移除了,我猜测可能是对于浏览器而言 Module Loader 的支持遭遇了一些技术上的难点,从而暂时性的舍弃了这一 feature。但是一个原生支持的模块加载器是非常有意义的,相信它不久后还是会回 归到 ES 规范中 (目前由 WHATWG 组织在单独维护)。
  2. Class
    准确来说 class 关键字只是一个 js 里构造函数的语法糖而已,跟直接 function 写法无本质区别。只不过有了 Class 的原生支持后,js 的面向对象机制有了更多的可能性,比如衍生的 extends 关键字 (虽然也只是语法糖)。
  3. Promise & Reflect API
    Promise 的诞生其实已经有几十年了,它被纳入 ES 规范最大意义在于,它将市面上各种异步实现库的最佳实践都标准化了。至于 Reflect API,它让 js 历史上第一次具备了元编程能力,这一特性足以让开发者们脑洞大开。

关于 ES2016 的最重磅的消息莫过于 11 月初 es 标准委员会宣布将 Object.observe 从 ES2016 草案中移除了,尽管它已经是 stage2 几乎已经是事实标准。官方给出的解释是,这 3 年的时间前端世界变化实在太大,社区已经有了一些更优秀简洁的实现了 (polymer 的 observe-js),而且 React 带来的 immutable object 在社区的流行使得基于可变数据的 Object.observe 的处境变的尴尬,O.o 再继续下去的意义不大了。

除此之外,ES2016 的相关草案也已经确定了一大部分其他 new features。这里提两个我比较感兴趣的 new feature:

  1. async/await:协程。ES2016 中 async/await 实际是对 Generator&Promise 的上层封装,几乎同步的写法写异步比 Promise 更优雅更简单,非常值得期待。
  2. decorator:装饰器,其实等同于 Java 里面的注解。注解机制对于大型应用的开发的作用想必不用我过多赘述了。用过的同学都说好。

目前 ES2015/ES2016 都有了比较优秀的转译器支持 (没错我说的是 babel),但是也不是 all features supported,尝新的过程中需要注意。

至于 Typescript,你可以将它理解成加入了静态类型的 js 的超集。这是完全开源运作的一个语言,其领导人为 C#之父 Anders Hejlsberg,Angular 2 就使用它进行开发,感兴趣的同学可以了解一下。

WebAssembly

WebAssembly 选择了跟 ES2015 在同一天发布,其项目领头人是大名鼎鼎的 js 之父 Brendan Eich。WebAssembly 旨在解决 js 作为解释性语言的先天性能缺陷,试图通过在浏览器底层加入编译机制从而提高 js 性能。这个事情跟当时 V8 做的类似,V8 也因此一跃成为世界上跑的最快的 js 引擎。但是由于 js 是弱类型的动态语言,V8 很快就触碰到了性能优化的天花板,因为很多场景下还是免不了 recompile 的过程。因此 WebAssembly 索性将编译过程前移 (AOT)。WebAssembly 提供工具将各种语言转换成特定的字节码,浏览器直接面向字节码编译程序。其实在此之前,firefox 已经搞过 asm.js 做类似的事情,只不过 WebAssembly 的方案更激进。有人认为 WebAssembly 可能是 2016 年最大的黑马,如果 WebAssembly 能发展起来,若干年后我们看 js 编写的应用会像现在看汇编语言写出的大型程序的感觉。WebAssembly 项目目前由苹果、谷歌、微软、Mozila 四大浏览器厂商共同推进,还是非常值得期待的。

Web Components

Web Components 规范起草于 2013 年,W3C 标准委员会意图提供一种浏览器级别的组件化解决方案,通过浏览器的原生支持定义一种标准化的组件开发方式。Web Components 提出之际引发了整个前端圈的躁动,大家似乎在跨框架的组件化方案上看到了曙光。但是前端这圈子发展实在太快了,在当前这个时间 点,Web Components 也遭遇到了跟 Object.observe 相似的尴尬处境。我们先来看看 webcomponents 的几个核心特性:

  1. Shadow DOM
  2. Custom Element
  3. Template Element
  4. HTML Imports

其中 1、4 现在都能很容易的通过自动化的工程手段解决了 (shadow dom 对应的是 scoped css),而自定义标签这种事情不论是 React 还是 Angular 这类组件框架都能轻松解决,那么我用你 webcomponents 的理由呢?

另外 webcomponents 将目标对准的是 HTML 体系下的组件化,这一点跟 React 比就相对狭隘了 (但是这并不表明 React 把战线拉的那么长就不会有问题)。

不过原生支持的跨框架的组件还是有存在的意义的,比如基础组件库,只是在当前来看 web components 发展还是有点营养不良。期待 2016 年能有实质上的突破吧。

架构的变化

2015 年出现的新的技术及思路,影响最大的就是技术选型及架构了。我们可以从下面几点来看看它对前端架构上都有哪些影响。

组件化

React 的风靡使得组件化的开发模式越来越被广大开发者关注。首先要肯定的是,组件化是一个非常值得去做的事情,它在工程上会大大提升项目的可维护性及拓展性,同时会带来一些代码可复用的附加效果。但这里要强调的一点是,组件化的指导策略一定是分治而不是复用,分治的目的是为了使得组件之间解耦跟正交,从而提高可维护性及多人协同开发效率。如果以复用为指导原则那么组件最后一定会发展到一个配置繁杂代码臃肿的状态。

工程化

工程化是近年前端提到最多的问题之一,而且个人认为是当前前端发展阶段最有价值的问题,也是前端开发通往工业化时代的必经之路。这里不赘述,有兴趣的同学看我前阵子整理的一篇文章前端工程化知识点回顾

应用架构层 MVVM & Flux

MVVM 想必大部分前端都耳熟能详了,代表框架是 angular、vue、avalon。angular 在 1.2 版本之后加入了 controllerAs 语法,使得 controller 可以变成一个真正意义上的 VM,angular 整个架构也才真正能称之为严格的 MVVM(之前只能说是带有双向绑定的 MVC/MVP)。

Flux 是 facebook 随 React 一并推出的新的架构模型,核心概念是单向数据流。Flux 实质上就是一个演进版的中介者模式,不同的是它同时包装了 action、store、dispatcher、view 等概念。关于 Flux 对应用分层、数据在不同层之间只能单向流转的方式我是很赞成的。应用的分层在业务稍复杂的应用中都是很有必要的,它更利于应用的伸缩及拓展,副作用是会带来一定的复杂度。

业务数据层 Relay & Falcor

这一层对大部分前端来说可能是比较新的概念,其实我们可以这样理解:在一个完整的应用中,业务数据层指的就是数据来源,在 angular 体系中可以等同于 ngResource 模块 (准确来说应该是 $http)。

Relay 是 Facebook 推出的在 React 上应用 GraphQL 的框架,它的大致思路是:前端通过在应用中定义一系列的 schema 来声明需要的接口数据结构,后端配合 GraphQL 引擎返回相应的数据。整个事情对于前端来说意义简直是跨时代的,工业化典范!不仅能极大提升前后端协同的开发效率,还能增加前端对于应用完整的掌控力。但是目前来看问题就是实施过于复杂,而且还得后端服务支持,工程成本太高,这一点上 Meteor 显然做的更好。

Falcor 则是 Netflix 出品的一个数据拉取库,核心理念是单一数据源,跟 Redux 的单 store 概念一致。用法跟 Realy 类似,也需要前端定义数据 schema。另外还有一个新的 W3C 标准 api:fetch,它的级别等同于 XMLHttpRequest,旨在提供比 ajax 更优雅的资源获取方式,目前几个主流浏览器支持的都还不错,也有官方维护的 polyfill,几乎可以确定是未来的主流数据请求 api。

业务数据层是前端应用中比较新的概念,它的多元化主要会影响到应用的架构设计。

新的编程范式

函数式编程 (FP)

函数式编程 (functional programming) 是近年比较火爆的一个编程范式,FP 基于 lambda 演算,与以图灵机为基础的指令式编程 (Java、C++) 有着明显的差异。 lambda 演算更关注输入输出,更符合自然行为场景,所以看上去更适合事件驱动的 web 体系,这点我也认同。但问题是,太多开发者看到 redux 那么火爆就急着学 redux 用 js 去玩函数式,我觉得这个有待商榷。如果你确实钟情于函数式,可以去玩玩那些更 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 反而更具前景。

PostCSS & cssnext

PostCSS 作为新一代的 css 处理器大有取 Sass/Less 而代之的趋势,Bootstrap v5 也有着基于 PostCSS 去开发的计划。但从本质来讲它又不算一个处理器,它更像是一个插件平台,能通过配置各种插件从而实现预处理器跟后处理器的效果。
cssnext 官方口号是“使用来自未来的语法开发 css,就在今天!”,但是 cssnext 又不是 css4,它是一个能让开发者现在就享受最新的 css 语法 (包括自定义属性、css 变量等) 的转换工具。

写在最后

从前端的发展现状来看,未来理想的前端技术架构应该是每一层都是可组装的,框架这种重型组合的适用场景会越来越局限。原因在于各部件不可拆卸会增加架构的升级代价同时会限制应用的灵活性。举个例子,我有一套面向 pc 端的后台管控平台的架构,view 层采用 angular 开发,哪天我要迁移到移动端来,angular 性能不行啊,我换成 vue 就好了。哪天觉得 ajax 的写法太挫,把 http 层替换成 fetch 就好了。又有一天后端的 GranphQL 平台搭好了,我把 ngResource 换成 relay 就 OK 了。

这种理想的方式当然是完全正确的方向,但是目前来看它对开发者 / 架构师的要求还是太高,工业级别上一套带有约束性的框架还是有相当的需求的。虽然美好但是组合的方式也不是没有问题,各种五花八门的搭配容易造成社区的分化跟内耗,一定程度上不利于整个生态圈的发展。

近年前端生态的野蛮发展影响最大的应该就是新产品的技术选型了,乱花迷人眼,我们很难设计出一套适应大部分场景、而且短时间内不会被淘汰的架构。前端的变化太快通常会导致一些技术决策的反复,今天的最佳实践很可能明天就被视为反模式。难道最合适的态度是各种保留各种观望,以不变应万变?那句话怎么说的来着?从来没有哪个圈子像今天的前端一样混乱又欣欣向荣了。有人说 2015 年或许是大前端时代的元年,目前看来,如果不是 2015,那么它也一定会是 2016 年。

最后引用计子 winter 的一句话作为结语吧:

前端一直是一个变化很快的职能,它太年轻,年轻意味着可能性和机会,也意味着不成熟和痛苦。我经常担心的事情就是,很可能走到最后,我们会发现,我们做了很多,却还是一无所获。所幸至今回顾,每年还是总有点不同,也算给行业贡献了些经验值吧。

本文作者刘奎( @kuitos ),原文地址,本文由作者授权转载,相对原文有删减。

作者介绍:
刘奎,一个后端出身的伪前端工程师,如今专注于前端领域。目前在国内一家从事电商 CRM 服务的互联网公司供职,主要负责公司各产品的前端架构、技术选型及前端体系化搭建。涉猎的领域包括 SPA 应用架构、前端工程化、web 标准等等。中度代码洁癖症患者,唯标准论的教条主义者。

2015-12-29 03:006536

评论

发布
暂无评论
发现更多内容

数据库周刊62丨央企2021年数据库成交公告,国产占90%;流数据库HStreamDB开源;MySQL主从双写导致数据丢失;Oracle 19c升级最佳实践;PG日常工作分享;MySQL MGR运维指南;SQL语法手册……

墨天轮

MySQL 数据库 sql postgre

基于感染原理判断图的连通性算法

大奎

图算法 子图 连通性

Cobar SQL审计的设计与实现

捉虫大师

Disruptor Skywalking cobar 数据库中间件

Flink SQL 在网易云音乐的产品化实践

Apache Flink

flink

java好还是嵌入式好?做IT开发该如何选择

cdhqyj

Java 编程 发展 开发 嵌入式

最全面试考点与面试技巧,面试必问

欢喜学安卓

android 程序员 面试 移动开发

安卓最全面试考点与面试技巧,大厂直通车!

欢喜学安卓

android 程序员 面试 移动开发

【LeetCode】位1的个数Java题解

Albert

算法 LeetCode 3月日更

【Doris Weekly】2020.03.08~2021.03.21

ApacheDoris

【Doris Weekly】

字节跳动单点恢复功能及 Regional CheckPoint 优化实践

Apache Flink

flink

力扣(LeetCode)刷题,简单题(第16期)

不脱发的程序猿

面试 LeetCode 28天写作 算法面经 3月日更

精选2021互联网大厂Java核心面试题库(金三银四面试必备)

比伯

Java 编程 架构 面试 程序人生

【遇见Doris】基于Apache Doris的小米增长分析平台实践

ApacheDoris

问题排查 | 客户端突如其来的“白屏”等待

蚂蚁集团移动开发平台 mPaaS

html5 移动开发 mPaaS 离线包

【IstioCon 2021】最佳实践:从Spring Cloud 到 Istio

华为云原生团队

开源 Kubernetes 云原生 istio 服务网格

书单|互联网企业面试案头书之架构师篇

博文视点Broadview

架构

技术实践丨Prometheus+Grafana搭建HBase监控仪表盘

华为云开发者联盟

开源 Grafana Prometheus HBase 开源数据库

uni-app跨端开发H5、小程序、IOS、Android(六):uni-app事件绑定

黑马腾云

微信小程序 uni-app 大前端 iOS Developer 3月日更

力扣(LeetCode)刷题,简单题(第15期)

不脱发的程序猿

LeetCode 编程之路 28天写作 算法面经 3月日更

一文了解数据库资源管理技术

华为云开发者联盟

数据库 存储 GaussDB(DWS) 资源管理

EGG公链强势来袭!去中心化社交革命先驱EFTalk

币圈那点事

对于移动开发,人工智能的到来意味着什么?

故胤道长

人工智能 机器学习 ios开发 Android开发

墨天轮精选:数据库问答集萃第一期-2021

墨天轮

MySQL 数据库 sql dba

Flink架构体系

大数据技术指南

大数据 flink 28天写作 3月日更

Spark常见的故障排除

五分钟学大数据

大数据 spark 28天写作 3月日更

开发也要防“沉迷”?IDEA插件教程详解

京东科技开发者

Java 开发 IntelliJ IDEA

终于有阿里高工把SpringBoot+SpringCloud+Docker+MQ整合在一起了

Java架构追梦

Java 架构 微服务 springboot SpringCloud

揭秘盒马鲜生,如何打破收益增长天花板!

博文视点Broadview

ThreadLocal 慌不慌?

叫练

JVM ThreadLocal 引用 软引用

解读2015之前端篇:工业时代 野蛮发展_语言 & 开发_刘奎_InfoQ精选文章