graphql和rest_如何使用GraphQL使您的网站整洁和可维护

穆乐逸
2023-12-01

graphql和rest

REST API services, SQL databases, markdown files, text files, SOAP services… can you think of yet another way to store and exchange data and content? Production websites usually work with several different services and ways to store data, so how can you keep the implementation clean and maintainable?

REST API服务,SQL数据库,降价文件,文本文件,SOAP服务……您能想到另一种存储和交换数据及内容的方法吗? 生产型网站通常使用几种不同的服务和方法来存储数据,那么如何保持实施的清洁性和可维护性呢?

Every Node.js website, regardless if it is a single page application or a regular site, needs to connect to a third-party service or system. At the very least it needs to get content from markdown files or a headless CMS. But the need for other services quickly surfaces. First, it’s a contact form — you need to store its submissions. Then it’s a full-text search — you need to find a service that enables you to create indexes and search through them. And the list goes on and on depending on the size of your project.

每个Node.js网站,无论是单页应用程序还是常规站点,都需要连接到第三方服务或系统。 至少它需要从markdown文件或无头CMS中获取内容。 但是对其他服务的需求Swift浮出水面。 首先,这是一个联系表单-您需要存储其提交的内容。 然后,这是一个全文搜索-您需要找到一个服务,使您能够创建索引并对其进行搜索。 列表会根据项目的大小而不断变化。

What is the problem with that? Well, nothing at first. When you are motivated to finish a project you create a component for each of these functionalities. Communication is encapsulated within the respective components, and after a few quick tests, you are happy it all works. The customer is happy the project was delivered before the deadline, and as a side effect, you also became an expert on a Content as a Service API, form submission services, and automatic search index rebuilding.

这是什么问题? 好吧,一开始什么都没有。 当您有动机完成一个项目时,您将为每个功能创建一个组件。 通信封装在各个组件中,在进行了一些快速测试之后,您很高兴一切都能正常进行。 客户对项目在截止日期之前交付感到高兴,并且副作用是,您还成为了内容即服务API,表单提交服务和自动搜索索引重建的专家。

You got the website up and running so quickly that you got promoted! And the knowledge of the project and its details with you.

您启动网站并运行如此之快,以至于获得了提升! 以及您的项目知识和详细信息。

In a few weeks, your colleagues are asked to do some changes to the project. The customer wants to use a different search provider as the original one is too expensive. The developers are also working on another project that needs a contact form, so they thought about using the same component, but store the submissions in a different service. So they come to you asking about the specifics of your implementation.

几周后,您的同事被要求对该项目进行一些更改。 客户想要使用其他搜索提供商,因为原始搜索提供商太昂贵了。 开发人员还正在研究另一个需要联系表的项目,因此他们考虑使用相同的组件,但是将提交的内容存储在其他服务中。 因此,他们来找您询问实现的细节。

When you finally give up searching your memory, they will need to do the same research as you did originally to figure out the implementation. The UI is so tightly coupled with the functionality, that when they want to reuse the components, they will probably end up implementing them again from scratch (and maybe copy-pasting bits and pieces of the old code).

当您最终放弃搜索内存时,他们将需要与最初为确定实现而进行的研究相同。 UI与功能紧密耦合,以至于当他们想要重用这些组件时,他们可能最终将再次从头开始实现它们(可能还需要复制粘贴一些旧代码)。

正确的抽象水平 (The Right Level of Abstraction)

So how can we avoid these issues to keep our code maintainable and clean? Take a look at the graphic above where I divided the communication with third-party services and the UI. The specifics of each external service API are implemented in the middleware on the back-end of the website. The components on the front-end all use a single way to fetch and submit data — GraphQL.

那么,如何避免这些问题来保持代码的可维护性和整洁性呢? 看一下上面的图形,其中我将通信与第三方服务和UI进行了划分。 每个外部服务API的细节都在网站后端的中间件中实现。 前端组件全部使用一种获取和提交数据的方式-GraphQL。

GraphQL (GraphQL)

So what is GraphQL and why use it to communicate between front-end and back-end? GraphQL is a query language, a protocol, that was founded exactly for this purpose — to decouple the data the website front-end needs from the queries required to fetch them. It is similar to a REST API from a functionality point of view as it enables you to query for data. For more information check out the GraphQL homepage.

那么,GraphQL是什么?为什么要使用它在前端和后端之间进行通信? GraphQL是一种查询语言,一种协议,正是为此而建立的-将网站前端所需的数据与获取它们所需的查询分离。 从功能的角度来看,它类似于REST API,因为它使您可以查询数据。 有关更多信息,请查看GraphQL主页

The main difference is in the way you ask for the data. Let’s say a new developer on the project is tasked with creating a blog page. The page should display blog posts that are stored within a headless CMS. I am using Kentico Cloud, which is a Content as a Service (CaaS) platform allowing you to store various types of content in clear hierarchical structures and obtain the content via a REST API. Therefore the GET request for data using a REST API could look like this:https://deliver.kenticocloud.com/{projectID}/items?system.type=blog_post

主要区别在于您要求数据的方式。 假设该项目的新开发人员负责创建博客页面。 该页面应显示存储在无头CMS中的博客文章。 我使用的是Kentico Cloud ,它是一个内容即服务(CaaS)平台,允许您以清晰的层次结构存储各种类型的内容,并通过REST API获取内容。 因此,使用REST API的GET数据请求可能看起来像这样:https://deliver.kenticocloud.com/ {projectID} /items?system.type=blog_post

Sample response would be:{  "items":[      {        "system":{          "id":"0282e86e-8c72–47f3–9d3d-2acf93a8986b",        ...        "last_modified":"2018–09–18T10:38:19.8406343Z"      },      "elements":{          "title":{            "type":"text",          "name":"Title",          "value":"Hello from new Developer Evangelist"        },        "content":{          ...        }        ...      }    }  ]}

样本响应为:{“项目”:[{“系统”:{“ id”:“ 0282e86e-8c72–47f​​3–9d3d-2acf93a8986b”,...“ last_modified”:“” 2018–09–18T10:38:19.8406343 Z“},” elements“:{” title“:{” type“:” text“,” name“:” Title“,” value“:” Hello from new Developer Evangelist“},” content“:{.. 。} ...}}]}

The response contains data of all blog posts in JSON form. As the page displays only a list of blog posts, a lot of returned data (starting with content field) are redundant as we do not need to display them. To save bandwidth (which you usually pay for), the developer would need to use additional columns filter:https://deliver.kenticocloud.com/{projectID}/items?system.type=blog_post&elements=title,image,teaser

响应以JSON格式包含所有博客文章的数据。 由于页面仅显示博客文章列表,因此许多返回的数据(从“ content字段开始)是多余的,因为我们不需要显示它们。 为了节省带宽(通常需要付费),开发人员将需要使用其他columns过滤器:https://deliver.kenticocloud.com/ {projectID} /items?system.type=blog_post&elements=title,image,teaser

They need to know the specifics of the API and probably have its reference open in another browser window while building the query.

他们需要了解API的细节,并可能在构建查询时在另一个浏览器窗口中打开其引用。

Getting the same data with GraphQL is much easier. Its schema is natively describing what the front-end is capable of rendering. The developer needs to specify what data to fetch in graph notation:query BlogPosts {  getBlogPosts {    elements {      title      image      teaser    }  }}

使用GraphQL获得相同的数据要容易得多。 它的架构本身就是在描述前端能够呈现的内容。 开发人员需要以图形表示法指定要提取的数据:query BlogPosts {getBlogPosts {elements {title image teaser}}}

(Find more examples of GraphQL queries in this Why GraphQL? article by Shankar Raju.)

(在 Shankar Raju撰写的 Why Why GraphQL? 文章中 找到GraphQL查询的更多示例 。)

Now when you decide to switch the content storage from headless CMS to markdown files or SQL database, the implementation of the blog page will not change. The GraphQL query will still look the same.

现在,当您决定将内容存储从无头CMS切换到降价文件或SQL数据库时,博客页面的实现将不会更改。 GraphQL查询将仍然相同。

How is that possible? Let’s look under the hood for a moment. The separation of the front-end implementation from external services is achieved using the following parts:

那怎么可能? 让我们稍候片刻。 前端实现与外部服务的分离使用以下部分来实现:

  • GraphQL schema

    GraphQL模式
  • GraphQL resolvers

    GraphQL解析器
  • Apollo server

    阿波罗服务器

GraphQL模式 (GraphQL Schema)

GraphQL schema is very much like class diagrams. It specifies the data models, like BlogPost or FormSubmission, and GraphQL queries.

GraphQL模式非常类似于类图。 它指定数据模型,例如BlogPostFormSubmission以及GraphQL查询。

Above you can see an example data models schema of a simple website. Note that there are undefined types like SystemInfo or AssetElement. I omitted them in the graphic as they will be generated later by the headless CMS type generator automatically.

在上方,您可以看到一个简单网站的示例数据模型架构。 请注意,存在未定义的类型,例如SystemInfoAssetElement 。 我在图形中省略了它们,因为它们稍后将由无头CMS类型生成器自动生成。

Queries and mutations (calls that may modify and store data) then describe how the data in these models are fetched and manipulated, like getting data for BlogPost or submitting a FormSubmission. It is like a class diagram for the middle data layer of the website.

查询和变异(可能会修改和存储数据的调用)然后描述如何获取和操纵这些模型中的数据,例如获取BlogPost数据或提交FormSubmission 。 它就像网站中间数据层的类图。

解析器 (Resolvers)

Resolvers are the actual implementations of the queries defined above, like MySQL resolver, Kentico Cloud resolver, and others. They are assigned to specific queries of the schema and are responsible for processing them. So when a front-end component wants to fetch blog posts using GraphQL query getBlogPosts, the server selects and invokes the registered resolver for that query (Kentico Cloud resolver). The resolver uses REST API of the headless CMS to fetch the content in JSON and provides it as an object array back to the component.

解析器是上面定义的查询的实际实现,例如MySQL解析器,Kentico Cloud解析器等。 它们被分配给模式的特定查询,并负责处理它们。 因此,当前端组件想要使用GraphQL查询getBlogPosts获取博客帖子时,服务器将选择并调用该查询的已注册解析器(Kentico Cloud解析器)。 解析器使用无头CMS的REST API来获取JSON中的内容,并将其作为对象数组提供给组件。

In this simple case, the resolvers are matched to queries and mutations 1:1, but a resolver can be signed up to as many of them as it can handle. The MySQL resolver currently has nothing to do, but later may come handy when the website functionality grows, and we decide to store some sensitive user inputs locally using a database.

在这种简单情况下,解析程序将与1:1的查询和变异匹配,但是可以对解析程序进行签名,使其可以处理的数量尽可能多。 MySQL解析器目前无事可做,但随着网站功能的发展,以后可能会派上用场,我们决定使用数据库在本地存储一些敏感的用户输入。

阿波罗将他们全部联系起来 (Apollo Connects Them All)

The last piece of the puzzle is the Apollo server. It’s the glue that connects all these parts. Apollo is a library, a framework, that connects GraphQL schema to a HTTP server in Node.js. I am personally using Express as a HTTP server, but you may also like Connect, Restify or Lambda.

最后一个难题是Apollo服务器。 连接所有这些部分的是胶水。 Apollo是一个库,一个框架,将GraphQL模式连接到Node.js中的HTTP服务器。 我个人将Express用作HTTP服务器,但您也可能喜欢Connect,Restify或Lambda

Apollo has two parts — server and client. The server works as a host for the GraphQL schema and handles the GraphQL requests. So whenever the front-end invokes a GraphQL query, Apollo server looks up the right resolver, waits for it to process the data and passes along its response. Apollo server is often used as a simple converter from any service interface to GraphQL when you need to integrate with a system that does not support GraphQL natively.

Apollo有两个部分-服务器和客户端。 该服务器充当GraphQL架构的主机,并处理GraphQL请求。 因此,每当前端调用GraphQL查询时,Apollo服务器都会查找正确的解析器,等待其处理数据并传递其响应。 当您需要与本机不支持GraphQL的系统集成时,Apollo服务器通常用作从任何服务接口到GraphQL的简单转换器。

Apollo client is a module that plugs into the front-end of a website and enables execution of GraphQL queries.

Apollo客户端是插入网站前端并启用GraphQL查询的模块。

加快速度的样板 (Boilerplate to Speed Things Up)

In this article, I explained how to separate concerns, isolate third-party service connectors, and enable rapid development of front-end components using GraphQL without knowing the specifics of all used services.

在本文中,我解释了如何在不知道所有已使用服务的细节的情况下如何分离问题,隔离第三方服务连接器以及启用使用GraphQL的前端组件的快速开发。

My next article with live demo dives more into using Apollo with GraphQL schema, shows how to define the schema and implement resolvers. It also presents a boilerplate that has all these tools set up and ready for your development.

我的下一篇关于现场演示的 文章将深入探讨如何将Apollo与GraphQL模式结合使用,展示如何定义模式和实现解析器。 它还提供了一个样板 ,其中设置了所有这些工具并为您的开发做好了准备。

翻译自: https://www.freecodecamp.org/news/how-to-make-your-website-clean-and-maintainable-with-graphql-13fe06098656/

graphql和rest

 类似资料: