React库+GraphQL服务器+Relay架构联合作战(上)

IT科技2025-11-05 12:26:368

 【摘要】本系列文章较全面地分析了时下流行的构联React库、GraphQL服务器以及Relay架构模式各自的合作功能特征,并通过一个具体的战上实例向你展示它们是如何相互配合来完成一款Web应用的开发的。本篇属于本系列的构联上篇,侧重于React库、合作GraphQL服务器和Relay架构各自功能及其关系解析。战上

概述

不同于如AngularJS和Ember这样的构联框架,React是合作一个客户端库,其中提供了一组有限的战上函数,而且该库几乎独立于构建应用程序其他功能时所可能需要的构联其他库。从根本上说,合作React提供了客户端UI组件功能,战上其中提供了一种机制来创建组件、构联管理组件中的合作数据,渲染组件,战上以及复合小组件来构建更大的组件。React可以用于多种情景下,无论数据来自何处、 如何检索数据或如何把数据作为一个更大的应用程序的一部分进行管理的高防服务器。为了有效地对付这些问题,需要利用其他的库和模式。一个用于React应用程序的常见模式是Flux。

人们开发Flux的目的是把它作为MVC(模型-视图-控制器)模式的一种替代方法,来管理响应动作的数据流。与MVC的双向数据流动不同,Flux依赖于系统中的各个部件之间的单向数据流。Flux是Facebook创建的,因为他们的开发人员发现很难了解采用MVC模式开发的大型应用程序中的数据运动规律。

不同于MVC模式所采用的多环路数据流,Flux使用的是单环路数据流方案。数据仅沿着一条线路流动,这条线路是亿华云:动作(Action)->调度器(Dispatcher)->存储(Store)(或多个存储)->组件(即视图)->动作。

其中,动作(Action)表示某种进入系统的事件。这可能是用户生成的,如请求刷新数据的按钮单击事件,或者也可能是通过一个Web套接字接收消息事件。然后,这个动作被传递给调度器将它发送到所有的存储。调度器其实只不过是一个转发机制。它不懂动作是什么,动作所传递的数据的含义,而也不懂得与该动作相关的每个存储的功能。它只是把动作调度给所有的存储,然后每个存储决定是否应该处理这一动作。存储负责维护数据的本地副本,强制实施业务规则并通知新数据的组件,企商汇以便能刷新它们。你可以认为存储是维护应用程序状态的,而整个Flux流程本质上就是一个状态机。因此,React组件利用了状态机模式。在某种意义上,Flux利用与此相同的状态机模式来架构整个应用程序。

虽然Flux是解决数据流问题的一种模式,但它本身并没有提供实现这种模式的技术。若要使用Flux模式,开发人员不得不创建系统中所有的组件,除了Facebook提供的调度器之外。创建一个Flux系统是相对比较容易的,但它需要大量的样板代码。在这方面,它面临与Backbone.js同样的问题。启动和运行系统是很容易的,但最终需要大量的编码。

Flux进化过程

当开发人员使用Flux时,他们开始想办法来把样板代码重构到可重用的库中。此外,他们还能够确定出Flux中的子模式,这使得对于应用程序中数据流的分析判断更为容易,而且还在而不牺牲Flux一般优点的情况下减少应用程序的复杂性。这些子模式包括:把应用程序中的多存储减少到一个存储;把调度器与存储结合到相同的组件(当只有一个存储时这是很重要的)中;而且,还能够把诸多组件封装到一个容器中,此容器中可以在黑箱中创建动作、调度和进行存储管理。如今,许多Flux的衍生产品不再仅仅局限于纯粹的Flux功能,而且还能够在保留其根本要素的同时避免Flux通常的缺点,即大量的样板代码的问题。

目前,虽然有很多Flux的衍生产品,但是Redux是更受欢迎的模式之一。Redux纯粹基于状态机概念和不可变数据的思想而构建。在该模式中,动作都由单一的“调度器-存储”来处理;这些“调度器-存储”对象使用reducer函数(它们本身是可以组合的)实现把一种状态转换到另一种状态。这就在极大地简化Flux模式的同时引进很多函数编程特征;一旦你彻底掌握这一技术,React应用程序编码将容易许多。

Relay是来自于Facebook团队的另一个Flux的衍生产品,此模式日渐普及。关于Facebook如何使用Relay以及其与Flux关系的处理方案的更多信息,请参考网址https://facebook.github.io/react/blog/2015/02/20/introducing-relay-and-graphql.html。

Relay框架功能分析

虽然Redux简化了应用程序的管理,但是在实际数据定位方面却不可知。它可以使用任何数据存储系统,但是再一次导致更多的样板代码(虽然少于Flux)问题。于是,出现了Relay (这是Facebook创建的另一个产品,其应用了其他大量的JavaScript开源产品,例如React,Relay,Immutable.js,GraphQL,Jest,Flow等),它的宗旨在于通过重构去除数据访问相关的样板代码部分,同时还引进另一种新的数据服务——GraphQL。GraphQL不同于传统REST服务的地方在于,它把数据视为一个图形,并力求以分层方式来描述该图形,从而使数据消费者自己指定他们需要的数据,而不是传统的REST服务中那样提供一组固定的数据集服务而不考虑消费者需求。

那么,Relay到底是做什么的呢?Relay是一个框架,它负责把React组件连接到GraphQL服务器,此连接是通过一个实现了动作、调度器和存储的容器实现的。开发人员不需要对动作、调度器和存储进行编程,而可以触发这些动作并通过Relay API来访问相应的结果。若要配置容器,开发人员必须提供GraphQL查询和突变片段(mutation fragments)向容器描述数据的图结构;此外,Relay还会负责照顾数据管理的所有细节。

Relay的确是一个框架(如Angular),而不是一个库。它的实现可以说是透明的——它需要通过React实现UI组件而且由GraphQL提供数据服务。一旦GraphQL服务器和React组件配置到位,Relay将接管并执行所有需要的操作。因此,使用Relay的关键是掌握配置过程。

此外,与框架Angular(它仅对客户端有专门需求)不同,Relay还要求GraphQL服务器接口来为Relay容器提供数据查询和变异操作。但是,只要通过特定的GraphQL接口提供数据,Relay并不在意如何存储数据。

因此,Relay需要后端和前端两个开发团队都要了解它的工作原理,并要求他们弄清程序的的每个部件(无论前端还是后端)是如何编码和配置的。

Relay与React的配合

本小节中,让我们从React的角度来研究一下Relay。程序员们可以使用多种语言对GraphQL服务器进行编码与配置,并部署到多种平台上。对于Node.js环境下的GraphQL实现来说,有一个称为graphql-relay(https://www.npmjs.com/package/graphql-relay)的包可以用于简化GraphQL服务器的编码和配置要求。在React方面,则存在一个名为relay-react(https://www.npmjs.com/package/react-relay)的包可用于配置Relay容器和路由,还能够激发动作来实现数据变异操作等。

Relay开发入门

入门Relay是有些难度的。因为该技术是如此之新而且有很多的竞争对手,所以,有关如何使用Relay的参考资源目前还相当有限。而提供资源的地方,一般提供的例子也是很有限的;为此,开发人员最终被迫去阅读博客文章、翻阅GitHub问题和正式的产品说明书才能创建一个简单的CRUD应用程序。此外,还需要搭建一个相当复杂的开发环境以及需要有一个正确配置的GraphQL服务器。因此,这样的任务对于JavaScript/前端开发新手而言可能相当艰巨。

作为准备工作,请首先克隆一下GitHub网站上的存储仓库(https://github.com/DevelopIntelligenceBoulder/react-flux-blog)到您的计算机上,并打开相应的文件夹blog-post-5+6。此文件夹包含一个完整的GraphQL/React/Relay应用程序。为了便该应用程序启动并运行起来,请打开一个终端,导航到文件夹blog-post-5+6中,并运行以下Gulp命令。

$ npm i $ npm i -g gulp eslint eslint-config-airbnb eslint-plugin-react@^4.3.0 webpack babel-cli babel-eslint eslint-plugin-jsx-a11y@^0.6.2 $ gulp $ npm run update-schema $ gulp $ gulp server 

现在,请打开微软的Edge浏览器(【译者注】微软专门为Windows 10配置的高性能浏览器),然后导航到下面的URL:http://localhost:3000。

你会注意到,页面中将显示一个小控件列表,并使用Bootstrap 4风格进行修饰,看起来相当漂亮。(【译者注】因某种原因原文并没有提供结果快照)

该项目的基本开发构架是典型的文件夹组织方式。其中,src文件夹中存放可编辑的源代码文件,而最终的部署文件夹是dist(源代码文件都要复制至此处),应用程序正是使用此处的文件执行的。复制过程是使用Gulp命令进行的;具体地说,是通过组合一些简单的复制文件命令、创建一个处理SASS文件的任务,还有一个针对JavaScript的Web打***程完成的。其中,Web打包处理机制使用Babel转译器把RelayQL、JSX和ES2015代码转换为 ES5.1兼容的可以在任何浏览器中执行的JavaScript代码。ES2015和JSX转译已经不是什么新技术,但对于RelayQL的转译却是一个新课题。

RelayQL与Babel-Relay插件

GraphQL服务器能够通过使用内省(introspection)机制自动生成结构(【译者注】原文中用词是schema,这个词在数据库表格设计中常用;而其他许多软件技术中也广泛使用这个词,而且经常译为“模式”或“架构”。为了区别本文中另两个词pattern和architecture,在此特意译为“结构”)。结构(schema)其实是一个JSON文件,其中描述的所有类型由特定的GraphQL服务器使用。结构中可以包含自定义和内置类型。Babel-Relay插件使用此结构来校验使用RelayQL编码形成的GraphQL片段(fragments)。这些片段是使用ES2015字符串模板编码的,一旦它们通过根据结构定义的校验就被转换为JavaScript代码。这种校验可以有效地防止 GraphQL错误的发生。

配置Babel-Relay插件也是生成结构(schema)最简单的方法是,直接使用从Relay网站(https://facebook.github.io/relay/docs/guides-babel-plugin.html)或Relay初学者工具包项目(https://github.com/relayjs/relay-starter-kit)中下载的例子。这些文件正是本文对应的Github存储库中所使用的,并遵从Relay官网上推荐的开发模式。

从Relay初学者工具包项目中,我们需要使用两个文件:build/babelRelayPlugin.js和scripts/updateSchema.js。其中,UpdateSchema.js文件将用于生成结构(schema),而babelRelayPlugin.js文件将使用结构文件来校验证GraphQL片段以及转换RelayQL代码。

GraphQL与Relay协作

通常情况下,要使用Relay需要修改标准的GraphQL服务器实现方案。我们可以使用一个名为graphql-relay(https://www.npmjs.com/package/graphql-relay)的包来帮助把基于Node.js的GraphQL服务器配置为Relay兼容型的。要配置成一个Relay特定类型的GraphQL服务器需要三个主要方面:对象标记(Object Identification)、类型连接(Type Connections)和突变(Mutations)。

通过使用一个全局唯一的ID值,对象标记允许Relay从GraphQL服务器查询实现了节点接口的任何类型。这个全局ID是base64编码的,其中包含类型名称和一个后面跟一个冒号的本地ID值。graphql-relay库提供了分别命名为toGlobalID和fromGlobalID的函数支持在全局 ID之间来回转换。另外,类型名称来自于在类型配置中指定的GraphQL自定义类型名称。通常情况下,本地ID值来自于数据存储机制,例如关系数据库中的标记(Identity)。请参考下面的代码:

import { nodeInterface } from ./../node-definitions; export const widgetType = new GraphQLObjectType({ name: Widget, description: A widget object, fields: () => ({ id: globalIdField(Widget), // more fields }), interfaces: () => [nodeInterface] }); 

在上面代码中,文件node-definitions.js(及其相关文件type-registry)的作用是:为通过节点接口使对象可用而提供配置与类型注册。

第二个Relay特定的配置,即类型连接(Type Connections),是建立父类型及其子类型之间的一对多关系的连接。这些连接是使用一种特殊的连接类型结构管理的。这些特殊的连接类型结构支持图中的边缘(graph edge)概念和游标(cursor)的概念,用于限制结果集与生成结果页面。可以配置连接和边缘类型以支持如元数据这样的附加属性,从而允许控制连接或边缘特性(例如加权的边缘等)。请参考下面的代码:

import { widgetType } from ./types/widget-type; import { connectionDefinitions } from graphql-relay; export const { connectionType: widgetConnection, edgeType: WidgetEdge } = connectionDefinitions({name: Widget, nodeType: widgetType}); 

上面代码中的ConnectionDefinitions函数用于创建Relay期望的结构中的连接类型。请参考下面的代码:

import { widgetConnection } from ../connections/widget-connection; // inside of fields function of viewer type declaration widgets: { type: widgetConnection, description: A list of widgets, args: connectionArgs, resolve: (_, args) => connectionFromPromisedArray(getWidgets(), args) } 

上面代码中,WidgetConnection类型是从widget-connection.js文件中导入的,用于配置查看器类型中的控件字段。包graphql-relay中还提供了一个名为connectionArgs的对象,该对象中包含通过Relay传递进来的用于处理连接的标准参数。这些参数包含的值用于游标操作。

第三和***一个Relay特定的配置是突变(mutation)配置。graphql-relay包中提供了一个专门的命名为mutationWithClientMutationId的帮助方法用于简化突变配置。有四个字段是必需的:突变名称、输入字段、输出字段和获取有效载荷的字段。在GraphQL中,所有的突变都将伴随一个查询来获知任何数据可能已被更改。Relay通过智能地决定突变后需要刷新哪些数据来进一步扩展了这种能力。

突变的名字是当React-Relay应用程序访问GraphQL服务器时用来调用突变的名字。输入字段对应于GraphQL中突变的args参数。输出字段描述了要从突变返回的类型的字段。***一个获取有效载荷的字段将执行实际的数据库操作并返回一个promise对象,该对象将推迟从GraphQL到应用程序的响应时间,直到该promise被解析结束为止。

小结

React和GraphQL联手,并辅助以Relay,将为构建Web应用程序提供一个很有前途的框架。虽然开发过程中需要不少的安装及配置工作,但是一旦这些工作完毕,开发过程将流畅地进行下去,消除了样板代码,并智能地处理数据管理问题。实践将会证明Relay框架很可能会成为构建下一代Web应用程序的游戏规则改变者。在本系列下篇文章中,我们将探讨使用React并配合以Relay来控制GraphQL资源的问题。

本文地址:http://www.bhae.cn/html/246a21399540.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

热门文章

全站热门

电脑强制关机后不显示错误解决方法(解决电脑强制关机后屏幕无错误提示的方法)

apt-get和apt-cache是Ubuntu Linux中的命令行下的包管理工具。 apt-get的GUI版本是Synaptic包管理器。该文中我们会展示apt-get和apt-cache命令的15个不同例子。示例:1 列出所有可用包复制代码代码如下:linuxtechi@localhost:~$ apt-cache pkgnames account-plugin-yahoojp ceph-fuse dvd+rw-tools e3 gnome-commander-data grub-gfxpayload-lists gweled .......................................示例:2 用关键字搜索包这个命令在你不确定包名时很有用,只要在apt-cache(LCTT 译注:这里原文是apt-get,应为笔误)后面输入与包相关的关键字即可。复制代码代码如下:linuxtechi@localhost:~$ apt-cache search web server apache2 - Apache HTTP Server apache2-bin - Apache HTTP Server (binary files and modules) apache2-data - Apache HTTP Server (common files) apache2-dbg - Apache debugging symbols apache2-dev - Apache HTTP Server (development headers) apache2-doc - Apache HTTP Server (on-site documentation) apache2-utils - Apache HTTP Server (utility programs for web servers) ......................................................................注意: 假如你安装了“apt-file”包,我们就可以像下面那样用配置文件搜索包。复制代码代码如下:linuxtechi@localhost:~$ apt-file search nagios.cfg ganglia-nagios-bridge: /usr/share/doc/ganglia-nagios-bridge/nagios.cfg nagios3-common: /etc/nagios3/nagios.cfg nagios3-common: /usr/share/doc/nagios3-common/examples/nagios.cfg.gz pnp4nagios-bin: /etc/pnp4nagios/nagios.cfg pnp4nagios-bin: /usr/share/doc/pnp4nagios/examples/nagios.cfg示例:3 显示特定包的基本信息复制代码代码如下:linuxtechi@localhost:~$ apt-cache show postfix Package: postfix Priority: optional Section: mail Installed-Size: 3524 Maintainer: LaMont Jones Architecture: amd64 Version: 2.11.1-1 Replaces: mail-transport-agent Provides: default-mta, mail-transport-agent .....................................................示例:4 列出包的依赖复制代码代码如下:linuxtechi@localhost:~$ apt-cache depends postfix postfix Depends: libc6 Depends: libdb5.3 Depends: libsasl2-2 Depends: libsqlite3-0 Depends: libssl1.0.0 |Depends: debconf Depends: cdebconf debconf Depends: netbase Depends: adduser Depends: dpkg ............................................示例:5 使用apt-cache显示缓存统计复制代码代码如下:linuxtechi@localhost:~$ apt-cache stats Total package names: 60877 (1,218 k) Total package structures: 102824 (5,758 k) Normal packages: 71285 Pure virtual packages: 1102 Single virtual packages: 9151 Mixed virtual packages: 1827 Missing: 19459 Total distinct versions: 74913 (5,394 k) Total distinct descriptions: 93792 (2,251 k) Total dependencies: 573443 (16.1 M) Total ver/file relations: 78007 (1,872 k) Total Desc/File relations: 93792 (2,251 k) Total Provides mappings: 16583 (332 k) Total globbed strings: 171 (2,263 ) Total dependency version space: 2,665 k Total slack space: 37.3 k Total space accounted for: 29.5 M示例:6 使用 “apt-get update” 更新仓库使用命令“apt-get update”, 我们可以重新从源仓库中同步文件索引。包的索引从“/etc/apt/sources.list”中检索。复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get update Ign http://extras.ubuntu.com utopic InRelease Hit http://extras.ubuntu.com utopic Release.gpg Hit http://extras.ubuntu.com utopic Release Hit http://extras.ubuntu.com utopic/main Sources Hit http://extras.ubuntu.com utopic/main amd64 Packages Hit http://extras.ubuntu.com utopic/main i386 Packages Ign http://in.archive.ubuntu.com utopic InRelease Ign http://in.archive.ubuntu.com utopic-updates InRelease Ign http://in.archive.ubuntu.com utopic-backports InRelease ................................................................示例:7 使用apt-get安装包复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get install icinga上面的命令会安装叫“icinga”的包。示例:8 升级所有已安装的包复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get upgrade示例:9 更新特定的包在apt-get命令中的“install”选项后面接上“-only-upgrade”用来更新一个特定的包,如下所示:复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get install filezilla --only-upgrade示例:10 使用apt-get卸载包复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get remove skype上面的命令只会删除skype包,假如你想要删除它的配置文件,在apt-get命令中使用“purge”选项。如下所示:复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get purge skype我们可以结合使用上面的两个命令:复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get remove --purge skype示例:11 在当前的目录中下载包复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get download icinga Get:1 http://in.archive.ubuntu.com/ubuntu/ utopic/universe icinga amd64 1.11.6-1build1 [1,474 B] Fetched 1,474 B in 1s (1,363 B/s)上面的目录会把icinga包下载到你的当前工作目录。示例:12 清理本地包占用的磁盘空间复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get clean上面的命令会清空apt-get所下载的包占用的磁盘空间。我们也可以使用“autoclean”选项来代替“clean”,两者之间主要的区别是autoclean清理不再使用且没用的下载。复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get autoclean Reading package lists... Done Building dependency tree Reading state information... Done示例:13 使用“autoremove”删除包当在apt-get命令中使用“autoremove”时,它会删除为了满足依赖而安装且现在没用的包。复制代码代码如下: linuxtechi@localhost:~$ sudo apt-get autoremove icinga示例:14 显示包的更新日志复制代码代码如下: linuxtechi@localhost:~$ sudo apt-get changelog apache2 Get:1 Changelog for apache2 (http://changelogs.ubuntu.com/changelogs/pool/main/a/apache2/apache2_2.4.10-1ubuntu1/changelog) [195 kB] Fetched 195 kB in 3s (60.9 kB/s)上面的命令会下载apache2的更新日志,并在你屏幕上分页显示。示例:15 使用 “check” 选项显示损坏的依赖关系复制代码代码如下:linuxtechi@localhost:~$ sudo apt-get check Reading package lists... Done Building dependency tree Reading state information... Done

解决电脑错误141的有效方法(快速修复电脑错误141,避免数据丢失)

将电脑光驱改装为音响的教程(简单改装让电脑光驱释放出音响魅力,探索DIY的乐趣)

艾泰utt512w的性能及特点剖析(高速传输与稳定性能,艾泰utt512w的亮点解析)

Mac电脑数据迁移教程(轻松迁移你的数据到新的Mac电脑)

按照上图,开启远程连接,并设置密码linux下可以使用系统给出的命令ncviewer hostname:0

其实在使用VPS的时候很多也用过面板来管理和维护网站,使用过KLOXO以及Virtualmin/Webmin面板,相比较而言还是KLOXO耗费的资源比较小。昨天晚上的时候,在一个VPS群里看到有朋友提到安装Froxlor面板更加节省资源。今天我先不把这几个面板做对比,先自己安装一下。国人站长比较常用的是centos以及安装的LNMP环境,老左也和大家一起学习一下,不知道成功与否,边做边记录。对于Apache服务器,有众多控制面板可供选择,例如最流行的cPanel、Direct Admin和Plesk,免费的也有webmin和kloxo,可是对于高性能的Nginx服务器却暂时没有发现有一个比较好的解决方案。Froxlor是一个网页版本的服务器后台控制面板,支持Apache, Lighttpd和Nginx等多服务器。界面清爽,而且操作后台的面板还支持中文,需要快速配置请使用froxlor一键安装包安装。安装 Froxlor本安装教程安装系统环境为 Ubuntu 15.04。你必须安装如 MySQL、Apache、或Python包等所有先决条件。添加 froxlor 库、更新及安装命令:复制代码代码如下:sudo /etc/init.d/apache2 restart 打开浏览器并输入:http://IP地址/froxlor重要提示:到了这一步,出现Web服务器的404错误,我只需要移动froxlor目录,froxlor包默认安装在/var/WWW移动到/var/www/html,然后打开浏览器继续,点击安装按钮。验证所有要求是否满足与否,然后点击继续。提供所需的Mysql,FQDN,管理等凭证,点击下一步。确保所有的服务都是功能性的,点击下一步。登录的用户名是:admin,密码安装时指定由你。仪表板将类似于下面。OK,安装完毕,现在你可以看看里面的具体功能了。

热门文章

友情链接

滇ICP备2023000592号-9