原文地址:http://www.csdn.net/article/2015-08-04/2825370-reactcss
2004年,对于前端社区来讲,是里程碑式的一年。Gmail横空出世,它带来基于前端渲染的原生应用级别的体验,相对于以前的服务端渲染网页可谓提高了一个时代,触动了用户的G点。自此,前端渲染的网站成为无数开发者追逐的方向。html
为了更好地开发前端渲染的“原生级别的”网站,包括Backbone和Angular在内的一系列前端框架应运而生,并迅速得到了大规模的采用。可是很快地,新的性能和SEO问题也接踵而来。几经尝试后,Twitter甚至从前端渲染重回服务器渲染,而Strikingly也面对过一样棘手的问题。前端
2014年,React进入咱们的视线。让人耳目一新的是,对于其余开源框架遇到的种种问题,React都自信地给出了解答。几乎没有犹豫,咱们开始使用React来重构Strikingly。若干年后,当咱们回望,也许会发现,2014年也是前端社区里程碑式的一年。react
React简介编程
React到底是什么?Facebook把它简单低调地定义成一个“用来构建UI的JavaScript库”。这个定义也许会让咱们联想到许多JavaScript模板语言(好比Handlebars和Swig),或者早期的控件库(好比YUI和Dojo),可是React所基于的几个核心概念使它与那些模板和控件库迥然不一样。事实上这几个核心概念很是超前,已经给整个前端世界带来了冲击性的影响。它们包括:后端
这几条简单的原则放在一块儿带来了大量的好处:设计模式
咱们来看一个例子:浏览器
这个React版的Hello World已经展示了React的一些核心特性。首先,HelloMessage是一个React组件;建立React应用的时候,咱们老是以组件为出发点。每一个组件的核心是一个render方法,在其中咱们把这个组件的props和state拼装到一个最终要渲染的模板中,而后返回这个模板(确切地说这里是一个UI描述而不是传统意义上的模板)。这段代码里看起来像HTML同样的部分就是著名的JSX语法,它是在React中描述“模板”的最佳方式。前端框架
如今,以var开头的第一段里咱们定义了一个叫HelloMessage的组件;下面的React.render这一行所作的,则是把这个组件渲染到document.body里——也就是咱们实际的页面上。但在使用〈HelloMessage/〉的时候,咱们作了另外一件事:name="John"。看起来很像HTML中的元素属性,可是既然JSX不是HTML,这个语法的做用是什么呢?实际上,这就是咱们向React组件传入props的方式。回头看第一段,咱们能够看到在组件的内部有对this.props.name的引用。这个name就是咱们刚刚指定的John!服务器
看到这里,若是你熟悉jQuery的话也许在想,这与$(document.body).html('Hello John') 有什么根本区别呢?
这就是虚拟DOM出场的地方了。咱们像写HTML同样写JSX,可是JSX并不会直接变成HTML和DOM。在幕后,React维护着一个虚拟DOM,而实际上被浏览器直接操做的“物理”DOM只是这个虚拟DOM的投影。虚拟DOM不依赖于浏览器环境,它能够运行在任何JavaScript执行环境。这就让下面的代码成为可能:
若是第二行有点眼熟,你没有猜错——这段代码发生在服务器端!是的,一样的 HelloMessage,咱们不只可让React在前端渲染到页面,一样能够在后端直接渲染成HTML字符串,而后把它返回给前端。服务端预渲染就这么天然地发生了。
React带来的革命性创新是前端世界过去几年最激动人心的变化。自从接触React以来,咱们深信React会完全改变客户端开发者(包括前端、iOS和Android)的开发体验。在下面的篇幅里,咱们想从四个大的方向——目标平台(Targets)、数据处理(Data)、工具(Tools)和新的挑战——分享一下React生态系统和社区的进展和将来趋势。
目标平台
对于虚拟DOM的讨论,不少人会说速度快过于真正的DOM。这样的讨论可让人快速入门理解React,可是真正写过React应用的人会明白速度并非虚拟DOM的精髓。咱们认为虚拟DOM的存在帮助咱们作到了两件事。第一是申明式UI。经过虚拟DOM,UI再也不是一个不断被更变的DOM,你只要申明UI是怎么生成的,React会自动帮你把UI的改变渲染到真正的DOM上。这种新的思惟方式让你能够不用手动操做真正的DOM。第二是多Target。咱们一直在讲Web,但React让咱们作到Web之外的Target。虚拟DOM更像是UI虚拟机,自动帮你映射到真正的实现上,能够是浏览器DOM、iOS UI、Android UI。甚至有人作到了React映射到终端文本UI。
多Targets是React社区经常在讨论的主要话题之一。多Targets的根本是提升开发者体验。开发者体验(DX,Developer Experience)是在React社区里多次被提起的概念。如何在保持同样的用户体验下,提升开发者体验,是包括React在内的前端社区正在思考的问题。事实上任何一家有多客户端的公司都面临着这样同一个问题:在各类客户端语言里从新造轮子。开发者须要学习新的语言、写和维护相似的功能。提高客户端开发者体验就是减小学习成本和维护成本。这就是React提倡的“Learn once,write everywhere”。
最近也有一些鼓舞人心的消息。Facebook内部Ads Manager iOS版本由7位前端工程师用React Native花了5个月完成。而Android版本,是同一班人,3个月内完成。代码重用率达到了87%。
多Targets也能够是在单个平台更深度的结合。来自React核心团队的Sebastian Markbåge在ReactEurope大会上给了一个让人目瞪口呆的演讲《DOM as a Second-class Citizen》。演讲中他畅想React直接输出到浏览器架构的底层(图1浏览器的渲染架构,图2为Sebastian Markbåge认为React能够作的事情)。
图1 浏览器的渲染架构
图2 Sebastian Markbåge认为React还能够作不少事情
姑且不谈该不应这么作,经过虚拟DOM打开了这样的机会就已经让咱们兴奋不已了。也说明了Facebook在设计React时已经考虑到超越DOM。想法确实很超前。
【服务端预渲染(Pre-rendering)】
对于其余主流前端框架,页面SEO和首次打开速度的问题都很让人头疼。Twitter当年由于首次打开速度过于慢甚至重回服务器渲染方案。一直以来人们一直在寻找一种只须要编写一次UI组件,先后端同时都能渲染的方案。若是能作到的话,咱们就能够在首次打开页面时先用服务端渲染页面HTML,当浏览器收到后已经能够显示页面。这样SEO和首次打开速度都能被解决。这种完美方案社区里称之为Isomorphic/Universal App。
React原生支持了Pre-rendering(服务端渲染)。因为有虚拟DOM,也就意味着咱们只须要后端运行JavaScript引擎就能渲染整个DOM。目前主流后端语言均可以运行V8 JavaScript引擎。好比Strikingly的后端使用Ruby on Rails,只须要使用开源的react-rails gem就能够在Rails后端渲染前端React组件。
使用服务端渲染时要注意window和document这些浏览器才有的全局变量是不存在的。React组件提供这两个lifecycle hook:componentDidMount和componentDidUpdate在服务器不会被运行,只有在前端才会运行。使用服务器渲染时若是要使用任何浏览器才有的变量须要把代码放到这两个lifecycle hook定义里。
数据处理
React定义本身为MVC中的View。这让前端开发者从V开始去思考UI设计。但如今针对数据操做和获取方式,社区里尚未一种公认的方法。这也是任何写React应用时最难处理的地方。
【Flux】
对于M和C,Facebook提出了Flux的概念。Flux是一个专门为React设计的应用程序架构:应用程序由Dispatcher、Store和View组成,其中的View就是咱们的React组件。Flux的核心是如图3所示的单向数据流动。
图3 单向数据流动为Flux的核心
应用程序中的任何一次数据变化都做为Action发起,通过Dispatcher分发出去,被相关的Store接收到并整合,而后做为props和state提供给View(React组件)。当用户在View上作了任何与数据相关的交互,View会发起新的Action,开启一次新的数据变化周期。这种单向性使Flux在高层次上比传统MVC架构和以Angular和Knockout为表明的双向数据绑定容易理解得多,大大简化了开发者的思考和Debug过程。
在Facebook把Flux做为一种设计模式(而不是已经作好的框架)宣布以后,几乎每月出现一新的Flux库,他们都有各自的特点,有的对服务器渲染支持比较好,有的运用了更多函数式编程的概念。不少Flux库更像是实验,这有助于React生态的生长,但不能否认的是,将来会有大量Flux库慢慢死去,而只有少数会存留下来或进行合并。
【GraphQL】
在构建大型前端应用时,前端和后端工程师经过API的方式进行合做。API也是双方的协议。如今主流的方式是RESTful API,然而在实践中,咱们发现RESTful在一些真实生产环境的需求下不是很适用。每每咱们须要构建自定义endpoint,而这违背了RESTful的设计理念。
举个例子,咱们想要显示论坛帖子、做者和对应的留言。咱们分别要发出三个不一样的请求。第二个请求依赖第一个请求结果返回的user_id,前端须要写代码协调请求之间的依赖。分别发出三个不一样请求在移动端这种网络不稳定的环境下效果很不理想。
为解决这类问题,工程师会自定义一些endpoint。对于这个例子,咱们能够创建一个/feeds的endpoint,集合了全部前端须要的结果:
可是咱们在某些场景上可能只须要post和user,不想要comments。这时难道要再定义一个feeds_without_comments的endpoint?随着需求的改变,自定义endpoint的方法每每使得API接口变得累赘,违背了RESTful的设计理念。而任何前端工程师须要的数据一旦要改变都须要后端工程师的配合,这下降了产品的迭代速度。
来自Facebook的GraphQL是我认为目前最接近完美的解决方法。后端工程师只须要定义能够被查询的Type System,前端工程师就可使用GraphQL自定义查询。GraphQL查询语句只须要形容须要返回的数据形状:
{ post(id:1){ id, title, user{ id, name }, comments{ id, name, comment } } }
GraphQL服务器就会返回正确的JSON格式:
GraphQL也原生支持了API版本控制,让你能够同时共存多个版本的客户端(包括Web和Mobile)。这些都会减小客户端工程师和后端工程师的耦合度,提升生产力。
今年7月刚推出了GraphQL的规范并开源了JavaScript GraphQL库。然而要让GraphQL成为主流,Facebook须要打造一个像React这样的生态系统。要想在你本身的应用上用GraphQL还必需要有后端语言提供GraphQL库的支持。好比Strikingly须要GraphQL Ruby库。这不只仅须要前端工程师。咱们认为这将会比React生态系统更难创建(见图4所示)。Facebook须要整个社区的参与才能达到。
图4 GraphQL生态系统
【Relay】
Relay是Facebook提出的在React上应用GraphQL的方案。React的基础单位是组件(Component),构建大型应用就是组合和嵌套组件。以组件为单位的设计模式是目前社区里最承认的,这也是前端世界的趋势之一。每一个组件须要的数据也应该在组件内部定义。Relay让组件能够自定义其所须要GraphQL数据格式,在组件实例化的时候再去GraphQL服务器获取数据。Relay也会自动构建嵌套组件的GraphQL查询,这样多个嵌套的组件只须要发一次请求。Relay将会在8月份开源。
【Immutability】
React社区接受了不少函数式编程的想法,其中受Clojure影响很深。对Immutable数据的使用就是来自Clojure社区。当年Om,这个用ClojureScript写的React wrapper在速度上竟然完虐原生JavaScript版本的React。这让整个社区都震惊了。其中一个缘由就是ClojureScript使用了Immutable数据。React社区里也冒出了Immutable.js,这让JavaScript里也能使用Immutable数据,完美弥补了JavaScript在负责数据对象比较的先天性不足。Immutable.js也成为了构建大型React应用的必备。甚至有在讨论是否把Immutable.js直接归入JavaScript语言中。咱们认为小型应用不会遇到虚拟DOM的性能瓶颈,引入Immutable.js只会让数据操做很累赘。
工具
工欲善其事,必先利其器。React的火爆得力于来自社区的工具,而React也推进了这些工具的进步。这里咱们想介绍几个React社区里比较受欢迎的工具。
【Webpack】
在React里,因为须要用到JSX,使用Webpack或Browserify这类工具编译代码已经渐渐成为前端工程师工做流程的一部分。Webpack是一款强大的前端模块管理和打包工具(见图5所示)。这里列出它的一些特性:
图5 前端模块管理和打包工具Webpack
【Babel】
ECMAScript 6(ES6)规范在今年四月刚敲定,React社区基本全面拥抱ES6。但目前还有不少浏览器不支持ES6。使用像Webpack这样的工具编译代码使得咱们能够在开发时使用ES6(或者更新版本),在上线前编译成ES5。编译工具中最引人注意的是Babel。前身为ES6to5,Babel是目前社区最火的ES6编译到ES5的代码工具,Facebook团队甚至已经决定转用Babel而再也不维护以前内部使用的jstranform。经过Loader机制,Webpack能够很是简易地和Babel结合应用。
【React-hot-reload】
在开发任何大型前端应用过程当中,咱们经常会由于一些小错误就须要从新刷新整个页面。React-hot-reload尝试解决这个问题,提升开发效率。他使用了Webpack的Hot Module Replacement功能,动态替换React组件的lifecycle hook定义,不用刷新页面也能够更新代码变化。
【React Developer Tool】
这款Facebook官方推出的Chrome插件可让你方便地在浏览器中直接查看React的组件结构。安装后,在Chrome开发者工具中会多出一个React Tab。界面就像DOM Inspector同样,只不过是看React组件结构关系。是开发React应用不可多得的工具之一。
挑战
React正在快速开拓着它的疆界,这意味在得到新的喜悦的同时,咱们也面临着许多新的挑战。如今围绕着几个大的议题,React社区仍没有达成定论,每周甚至天天都有新的实验项目在尝试这些问题的解决。
【动画】
一直以来你们都对动画应该在React里怎么表达为状态感到困惑。Cheng Lou的React Tween State是咱们认为最符合React思惟的作法。把位移存在State里,而后经过JavaScript动态渲染新的位置。不过你们对该作法是否能达到满意的速度一直持有保留态度。在今年ReactEurope的演讲中,他为咱们展示出了出色的效果和速度,很是值得一看。
在Strikingly,咱们对于动画则采起了比较实用主义的处理方式:咱们定义了一些容器组件,好比〈JQFade/〉和〈JQSlide/〉,在其中调用jQuery的动画方法来实现相应的Transition。这种方式在理论上并不彻底符合React的精神,不过到如今为止仍是可以知足咱们需求的。
【Flux库与Relay】
正如上文已经提到过的,目前Flux的各类实现可谓是百花齐放,其中还并无出现一个具备权威性的事实标准。Relay一样也是刚刚孵化不久的新生概念——全部这些意味着虽然Flux+Relay会带来生产力的飞升,要实际用上它们咱们还要待以时日。
【CSS】
CSS是一个有趣的话题:彷佛全部人都以为当前的CSS有深入的缺陷,可是对于怎么解决这些缺陷你们的意见却分红了两派各不相让:一派认为CSS“能够被修好”,而且致力于修好它,由此诞生了cssnext这样的项目;另外一派认为CSS从根本上做为诞生于一个古老时代的东西,已经不能适应大规模、组件化的现代开发流程,这一思想集中反映在Christopher Chedeau的演讲《React: CSS in JS》中;在其中他提出了CSS的七个根本问题,而后指出在JavaScript中直接使用inline CSS能够几乎“免费”地解决全部这些问题。在传统的Web开发最佳实践中inline CSS一直是被压制的反面实践,如今咱们却可以以一个全新的视角看待它,这也完美地例证了React真的是在给整个前端世界带来根本性的推进。
总结
在不久前的JSConf 2015上赫门提出了前端的摩尔定理:前端每18月会难一倍。前端之因此变化这么快,是由于咱们如今面临着史无前例的工程化挑战。今天的前端复杂度跟几年前彻底不是一个等级。这也促使社区要找到在这种复杂度下能保持开发效率和开发体验的工具和设计模式。React社区从其余领域(游戏渲染、ClojureScript、函数式编程)偷师学艺,结合前端面临的独特问题,提出了一系列解决方案。React社区在各方面都推进着前端社区往前进。这对整个社区都是好事。咱们也但愿前端各个框架能够互相学习,共同推进整个社区的发展。