关于GraphQL-附有TS/React/Nextjs/Go示例代码
首先
最近在Web开发中,越来越多地采用了SPA(单页应用)和BFF(后端便捷工具)的联合组合。本博客将解释如何使用Next.js创建SPA,并通过Go实现的GraphQL服务器与BFF进行协作。
BFF的意思是
BFF是指”Backend for Frontend”,即为特定的前端(例如:移动应用程序、网页)定制的后端接口。传统的常规API旨在适应许多不同的客户端,而BFF则专为特定客户端的需求而设计,能够提供针对该客户端优化的数据和功能。
BFF(Backend for Frontend)在微服务架构中非常受欢迎,每个前端团队拥有自己独特的BFF,使得前端团队能够独立于后端服务的细节和变化而运作。
GraphQL是什么?
GraphQL是Facebook在2015年開發的一種數據查詢語言和運行時環境。可以用作替代RESTful API,允許客戶端精確地獲取所需的數據。這樣可以避免獲取過多或過少的數據,提高網絡使用效率和性能。
GraphQL的特点
-
- 強力な型システム
-
- スキーマ定義により、APIの形状とデータ型を明確に定義。
-
- 柔軟なクエリ
-
- クライアントが必要なデータだけをリクエストし、サーバーはそれに応じたデータを返す。
-
- 単一のエンドポイント
- 複数のRESTエンドポイントの代わりに、1つのエンドポイントですべてのクエリと変更を処理。
基本概念(Basic concepts)
-
- SPA (Single Page Application)
-
- ブラウザ内で動的に再描画されるWebアプリ。サーバーから新しいページ全体を取得するのではなく、必要なデータだけを取得して表示内容を更新。
-
- BFF (Backend for Frontend)
-
- 特定のフロントエンド(モバイル、ウェブなど)のためのバックエンド層。フロントエンドの要件に合わせてAPIを提供。
-
- マイクロサービス
- 小さなサービスに分割されたシステム。それぞれのサービスは独立して動作・デプロイが可能。
技术堆栈的选择 de
-
- React + Next.js
-
- JavaScriptフレームワーク。SSRやISR、静的サイト生成が可能。
-
- GraphQL
-
- クエリ言語とサーバーサイドランタイム。データの取得や変更を効率的に行う。
-
- Go
- パフォーマンスが高く、簡潔で読みやすい言語。マイクロサービスの開発に適している。
项目的设置
- SPA
npx create-next-app my-app --typescript
-
- マイクロサービス
- 1.Goプロジェクトの初期化
go mod init bff
安装 gqlgen (用于Go语言的GraphQL服务器工具包)。
go get github.com/99designs/gqlgen
3. Gqlgen的初始设定
go run github.com/99designs/gqlgen init
GraphQL服务器的实现
模式定义
type Query {
hello: String!
}
type Mutation {
setHello(message: String!): String!
}
解决者
package main
import (
"context"
)
type Resolver struct{
message string
}
func (r *Resolver) Query() QueryResolver {
return &queryResolver{r}
}
func (r *Resolver) Mutation() MutationResolver {
return &mutationResolver{r}
}
type queryResolver struct{ *Resolver }
func (r *queryResolver) Hello(ctx context.Context) (string, error) {
return r.message, nil
}
type mutationResolver struct{ *Resolver }
func (r *mutationResolver) SetHello(ctx context.Context, message string) (string, error) {
r.message = message
return message, nil
}
服务器
import (
"log"
"net/http"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/playground"
)
const defaultPort = "8080"
func main() {
port := defaultPort
srv := handler.NewDefaultServer(NewExecutableSchema(New()))
http.Handle("/graphql", srv)
http.Handle("/", playground.Handler("GraphQL playground", "/graphql"))
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
log.Fatal(http.ListenAndServe(":"+port, nil))
}
SPA和BFF的协作
1. SPA下的Apollo Client设定
npm install @apollo/client graphql
在app.tsx中配置Apollo Client
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
const client = new ApolloClient({
uri: 'http://localhost:4000/graphql',
cache: new InMemoryCache()
});
function MyApp({ Component, pageProps }) {
return (
<ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
);
}
export default MyApp;
与微服务的协作
使用Go语言进行HTTP客户端操作。
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
response, err := http.Get("http://localhost:5000/service-endpoint")
if err != nil {
panic(err)
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}
终端点:http://localhost:5000/服务终端点
我們要啟動各種伺服器。
- SPA
npm run dev
- BFF
go run main.go
- マイクロサービス
go run main.go
总结
在现代Web开发中,BFF和SPA的组合非常重要。特别是通过使用GraphQL,数据的获取和操作变得非常灵活。我们介绍了使用Next.js和Go来实现这种组合的方法,但根据实际项目的需求,可以考虑各种扩展和定制。