@qinyun
2018-09-12T18:04:44.000000Z
字数 4295
阅读 1568
未分类
在过去几年中,JavaScript前端框架成为构建具有良好用户体验的Web和移动应用程序的主流方法。我个人很喜欢这些框架给我们带来的灵活性,但从另一方面来看,灵活性有点太过了。为了理解为什么会出现这种情况,让我们把时针往回拨,看看在JavaScript框架出现之前是如何构建应用程序的。
在这些流行的前端框架(AngularJS、Backbone和Ember)出现之前,我们在服务器端渲染模板,然后将生成的HTML页面发送到浏览器端。当时流行的框架包括:
Django(Python)——最初发布于2005年7月21日,大约13年前。
Ruby on Rails——最初发布于2005年12月13日,大约13年前。
Symphony(PHP)——最初发布于2005年10月22日,大约13年前。
这些框架以MVC(Model-View-Controller)开发结构的概念为基础。Model代表数据的“形状”,View是用于“显示”数据的模板,Controller用于“连接”二者。
当时肯定已经有JavaScript了,但我们说得更多的是jQuery滑块和一些可以用来制作弹跳效果的库……
基于这些框架构建的应用程序有一些问题,但总体来说一切都还好。然后有一天,Ryan Dahl有了一个很棒的想法,他认为JavaScript不应该只是用来做一些愚蠢的动画,于是他开发了Node.js的第一个版本,让开发人员可以在服务器端编写JavaScript。
Node.js——最初发布于2009年5月27日,大约9年前。
Express.js(后端)——最初发布于2010年11月16日,大约8年前。
Backbone.js(前端)——最初发布于2010年10月12日,大约8年前。
AngularJS(前端)——最初发布于2010年10月20日,大约8年前。
Ember.js(前端)——最初发布于2011年12月8日,大约7年前。
应用程序的开发方式开始出现重大的转变。之前完全由服务器端处理MVC框架开始出现分裂——一个是处理MC(Model和Controller)的服务器端,一个是使用上述JavaScript框架处理View的前端客户端。在一些早期框架中,它们还在View中包含了Model和Controller,也就是双重Model和Controller,一些在前端,一些在后端——现在看起来好像涉及了很多代码。
Facebook发展迅猛,并成为全球最大的Web应用程序,接踵而来的是一系列巨大的挑战。最令人头疼的一个问题是,如何在在标题栏中显示通知的数量。
用户希望在Facebook应用程序上看到通知数量实时更新,但这些通知数量通常不准确。问题在于,Web应用程序很难知道应用程序的某个部分发生了变化(例如,当你阅读时消息),然后再另一个位置显示变化的内容(例如,将未读通知数量减少一)。
这个可以通过重新加载页面来解决——但Facebook的1000名热情洋溢的员工认为是时候采取行动做一些不一样的事情了。于是,他们重新思考前端框架应该如何处理信息,并创建了React。
React(前端)——最初发布于2013年3月,约5年前。
这个新框架擅长于渲染HTML,但并没有提供太多有关“如何”开发应用程序的方式。他们还推出了Flux,最终发展成为Redux(Redo-Flux)。以下是2014/2015期间放在Flux网站上的视频,对Flux和React进行了介绍。
Redux将应用程序所有的动态信息都保存在一个JavaScript对象中。当应用程序的某个部分需要显示某些信息时,它将从服务器请求数据,更新这个JavaScript对象,然后向用户显示这些数据。通过将所有信息保存在一个地方,无论在什么位置,应用程序都能显示正确的信息,这解决了Facebook的通知更新问题。
于是一个新框架出现了,即React Redux。照理说,Facebook解决了他们的问题,从此以后就风平浪静了,不是吗?
问题在于,人们(包括我自己)开始使用单个JavaScript对象来保存所有的信息,包括服务器端提供的每一条数据。这样可以让所有信息保持最新,但也存在三个不足:
它需要大量额外的代码,你需要花费更多的时间。
存在“陈旧数据”,也就是说应用程序之前的状态数据可能是不需要的,你不希望这些数据继续存在。
对于新的开发人员来说,它的学习曲线经历冲破了天花板,导致他们很难掌握前端Web开发。
我们设法将一个相对简单的任务(向用户显示数据)从MVC框架转为单体前端应用,前端代码比后端多10倍。我最近开发了一个简单的应用程序,并使用WakaTime来测量我在编码上所花费的时间。结果如下:
React Redux前端库——32小时
Express + Mongoose后端库——4小时
我在前端花了比后端多8倍的时间。让我们深入了解一下为什么它需要这么多额外的代码。以下是基本的数据请求调用(例如获取所有用户)需要遵循的步骤:
1.创建组件以显示用户列表
2.创建对API的fetch调用
3.在状态中添加新字段
4.添加一个更新状态的操作
5.添加一个转换方法,用于执行fetch调用,并使用新操作更新状态
6.使用connect()将转换函数添加到组件中
7.使用connect()从Redux状态中提取数据
8.在组件的prop类型中声明转换函数和提取的数据字段
9.在componentDidMount()函数中调用转换方法
10.在DOM中渲染数据
总共需要10个步骤。在Ruby on Rails时代,我只需要将数据提供给HTML模板就可以获得相同的结果。我感觉有些东西需要做出改变。
Redux非常适合用来保持前端应用程序的同步,但它也带来了其他问题(如前所述)。
从本质上说,我们重写了整个前端,只为了解决一些琐碎的问题……
Facebook也意识到这一点,并开始推出GraphQL来解决这个些问题。GraphQL目前是一个热语,但我不确定是否有人真正理解为什么它会这么酷。
GraphQL与Redux完全不同。Facebook再一次为我们提供了一个惊人的产品,但仍然没有说明白为什么这个产品如此重要。
简单地说,GraphQL是一辆汽车,而Redux是一匹马。
我之所以将这两者比喻为马和汽车,是因为马和汽车几乎没有什么相似点——一个是四条腿的动物,一个是带轮子的机器。然而,它们都试图达成相同的目标,即让一个人去到他们需要去的地方。汽车在街道上行驶并使用燃料,而马是一种可以跳过岩石的动物。两者都有不同的优势和用例,但一般来说,汽车会比马更快地到达最终目的地。
官方文档将GraphQL描述为“一种API查询语言”,这样的描述模棱两可。基本上,它们所谓的查询语言是指用数百个HTTP端点替换API。但这项技术还很年轻,文档和相关支持技术仍然有点难以理解,所以学习曲线比较陡峭,请看下面的例子。
GraphQL将以下的端点:
GET /users/1234567890
POST /cars
PUT /example/endpoints
替换成自定义查询:
{
user(id: "1234567890") {
name,
}
}
然后返回:
{
"user": {
"name": "Luke Skywalker",
"email": "luke@iamyourfather.com"
}
}
因为只请求需要的数据,就不需要发出很多服务器请求,这意味着你不需要使用很多代码来处理这些服务器请求。因此,你可以避免编写大量不必要的代码,从而节省大量的时间。
简单地说,它不会取代Redux。但不管怎样,它鼓励你不要将所有信息保存在单个对象中。因为每个查询都只为应用程序的一部分获取数据——而不是全部。在应用程序范围的数据源中保存特定于应用程序某个部分的信息是一种反模式(并且根本不合逻辑)。
使用GraphQL可以移除对Redux的依赖,从而删除大量不必要的代码。
还需要注意的是,Redux和GraphQL可以在应用程序中共存。如果你已经使用了Redux,可以将GraphQL逐步集成到Redux应用程序中。这里是一些关于如何将两者结合起来使用的文档(https://s3.amazonaws.com/apollo-docs-1.x/redux.html)。
于是,Redux成为了一个可选项。你可以用它来解决一些琐碎的问题,但同时也带来了额外的开销,当然,你也可以考虑使用其他东西来完成这些任务。
Redux是当时解决页面局部刷新问题的一个好方法。然而,自从它出现以来,Web开发行业已经经历了指数级的增长,然后Web Socket出现了。
Web Socket是服务器端和客户端之间的开放连接,服务器端可以通过Web Socket告诉客户端何时做出更新。GraphQL通过订阅的方式直接支持Web Socket,于是我们就可以使用这些订阅来更新我们希望保持同步的应用程序的某些部分。
主要的区别在于,我们不是让客户告诉我们需要更新哪些东西(使用Redux时是这样的),而是让服务器端告诉客户端必须更新数据。我们得到的效果是一样的。以下是一些如何使用Mongodb或Mongoose直接实现Web Socket或订阅的示例:
GraphQL已经推出一段时间了,现在处于可以被用在生产环境中的阶段。不过,它的文档仍然不是很好理解,而且需要事先了解JavaScript和服务器端的相关知识。官方网站提供了一个非常好的教程(https://graphql.org/learn/)。
还有一些很有用的库可以帮助你逐步将其集成到现有产品中。不用担心,你不需要一步到位,随着时间的推移,这些库将帮你逐步转换你的应用程序。Apollo是一家目前在库方面做得很好的公司(https://www.apollographql.com/)。