摘要:前言兩篇文章學完了基礎篇原理篇,接下去便是實踐的過程,這個實踐我們使用了如下技術棧去實現一套任務管理系統,源碼就不公開了等穩定后再發布。后續我所在的公司網關團隊會持續實踐,爭取貢獻出更多的解決方案。
前言兩篇文章學完了GraphQL(基礎篇, 原理篇),接下去便是實踐的過程,這個實踐我們使用了如下技術棧去實現一套任務管理系統,源碼就不公開了, 等穩定后再發布。效果如下:
使用的技術棧有:
React16全特性
Antd構建UI界面
create-react-app搭建客戶端基礎
react-apollo完成客戶端請求的封裝和響應體的處理
bizcharts(g2)實現圖表
apollo-boost(graphql)完成客戶端數據請求
rxjs完成某部分響應式設計
全程使用ramda.js做函數式編程
Nest框架做服務器
數據庫選擇moogoose
passport搭配jsonwebtoken做用戶認證管理
graphql-server(@nest/graphql)實現服務端graphql請求的處理
如下圖:
分為兩大部分:client和server,其中client的目錄結構如下:
各個目錄的解釋在圖中已經體現。
server端的目錄結構如下:
各個目錄的含義的解釋在圖中已經體現。
因為我們主要是講graphql的應用,所以其余的細節忽略不說。至于Nest框架的使用,請參考文檔Nest.js
GraphQL的實踐實踐GraphQL我們不會直接用graphql-js,而是使用功能更加豐富、社區支持更多apollo-graphql。其文檔編寫的也是很詳盡,基本上所有的問題都可以在文檔上找到答案。推薦新手可以先按照Get started來入手
客戶端的實踐因為我們使用了apollo-boost,所以在前端入口文件上,要拿這個包進行一些初始化,得到apolloClient的實例(無關的代碼已經去掉):
import React from "react";
import ReactDOM from "react-dom";
import { ApolloProvider } from "react-apollo";
import ApolloClient from "apollo-boost"
... ...
const GW_BASE_URL = process.env.NODE_ENV === "production" ");"/graphql" : "http://127.0.0.1:8888/graphql"
const client = new ApolloClient({
uri: GW_BASE_URL,
// 需要設置這個,這樣每次請求的時候認證信息才會帶上
fetchOptions: {
credentials: "include",
},
// 緩存讀取配置
clientState: {
typeDefs,
resolvers,
},
// 設置這個是為了配合jwt
request: async (operation) => {
// get the authentication token from local storage if it exists
const token = localStorage.getItem("token");
operation.setContext({
headers: {
authorization: token ");${token}` : "",
Origin: location.href,
},
});
},
// 設置全局錯誤處理信息,這樣就不用每個請求都進行error處理
onError: (errObj) => {
if (errObj.graphQLErrors) {
const errorMsg = errObj.graphQLErrors[0].message;
if (errorMsg === "身份信息已過期,請重新登錄") {
... ...
message.info(errorMsg, 3, () => location.hash = "#/user/login");
} else if (errorMsg && (errorMsg as any).statusCode === 403) {
message.error("權限不足,請不要重試");
} else {
message.error(errorMsg);
}
}
},
});
ReactDOM.render(
,
document.getElementById("root"),
);
頁面級別的使用
每個頁面都會新建三個文件:
graphql.ts index.scss index.tsx
其中graphql.ts定義了客戶端的請求,比如:
import gql from "graphql-tag";
// 用來查詢所有的用戶
export const QUERY_USERS = gql`
query {
userList {
id
roles
team
mobile
staffCode
email
username
}
}
`;
而后在index.tsx文件中就可以使用這個查詢語句,如下:
整個流程是很清晰的,因為使用了typescript,所以在客戶端可以引用到服務端定義的返回類型,從而提高了代碼編寫的速度。
實踐出來的問題和想法react-apollo目前發現了個bug,如果我返回的數據的層級太深,比如達到了4層以上,數據更新到緩存的時候便會出錯。
關于graphql的本地狀態的管理略微復雜,如果有個請求的結果從一開始就一直被所有的頁面使用,一般一些公共的信息,比如用戶名等,這種情況下想要直接拿到的話是不大可能的,需要繞一大圈去實現,有點蛋疼~
分頁的功能分為游標式和skip式,很明顯游標式并不適用于web端,雖然游標式對數據是非常友好的。在移動端用游標式更加適合。
本地狀態管理是graphql的一個很厲害的功能,直接不需要任何數據管理框架,就可以實現數據的各種操作,這是一大亮點!
apollo-graphql也提供了開發者工具,可以在瀏覽器實時預覽當前緩存的所有數據Developer tools
因為服務端使用了Nest.js,所以沒有直接用apollo提供的服務器,而是用了Nest框架封裝出來適用于Nest框架的graphql包graphql。該包還是提供了很多功能的。
在app.modules.ts中,我們要去初始化graphql模塊(無關代碼已忽略):
@Module({
imports: [
GraphQLModule.forRoot({
// 指定服務端schema存放的位置
typePaths: ["graphql/schema.graphql"],
// 配置了該選項,可以自動根據代碼生成schema
autoSchemaFile: path.join(__dirname, "graphql/schema.graphql"),
buildSchemaOptions: {
},
// 可以自動生成types文件
// definitions: {
// path: path.join(__dirname, "types/graphql.ts"),
// },
debug: true,
playground: true,
context: ({ req }) => ({ req }), // 一定要這里設置req到上下文中,否則在guard中是拿不到這個req參數的
}),
],
controllers: [],
providers: []
})
每個業務目錄都會存在這么些文件:
我們在dto目錄下定義三種類型文件:xx.args.ts/xx.input.ts/xx.model.ts,分別定義下面三種情況
args對應請求不是Input類型的
input對應請求是Input類型的
model對應請求的響應體
而后在xx.resolver.ts中實現resolve函數,借助于修飾器,比如:
import { Query, Resolver, Args, Mutation } from "@nestjs/graphql"
@Resolver("User")
export class UserResolver {
@Query(returns => [UserItem])
... ...
async userList(): Promise{
return this.userService.getUserList();
}
}
UserItem在這里(user.model.ts)定義:
import { ObjectType, Field, ID, registerEnumType, Int } from "type-graphql"
... ...
@ObjectType()
export class UserItem {
@Field(type => ID, {nullable: true})
_id");true})
username");true})
email");
如此便完成了整個服務端數據流的過程??粗遣皇呛躤asy?。?/p>
數據庫的model和graphQL定義的model大致相同,二者如何更好地契合在一起?目前社區并沒有給出對應的解決方案。
因為graphql只有一個endpoint,所以打印請求就不能像之前restful那樣,需要一個與之對應的打印方案
如何結合swagger實現文檔級別的呈現?亦或是不需要swagger,而是依靠schema去呈現文檔給客戶端,值的深入研究,并給出解決方案
graphql號稱解決版本的兼容性問題是輕而易舉的,目前在本項目中并沒有體現到。
至此,三篇關于GraphQL的文章到此結束了,花了很多時間斷斷續續地學習,希望可以給大家呈現一份不一樣地文章,供大家思考。后續我所在的公司網關團隊會持續實踐GraphQL,爭取貢獻出更多的解決方案。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/7846.html
摘要:分鐘學是一個系列,簡單暴力,包學包會。一旦組件掛載后,會自動進行數據請求,前提是客戶端提供的和后端的相符。如果回調返回直接不作請求。在組件內進行分頁請求之前提到了,這個裝飾器為添加了對象,其中有個函數為。 21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數據修改本...
摘要:本文實例代碼什么是是一種面向數據的查詢風格。概述前端的開發隨著框架全面普及,組件化開發也隨之成為大勢所趨,各個組件分別管理著各自的狀態,組件化給前端仔帶來便利的同時也帶來了一些煩惱。 showImg(https://segmentfault.com/img/remote/1460000018479542?w=4928&h=3280); 本文首先介紹了 GraphQL,再通過 Mongo...
摘要:學習之道簡體中文版通往實戰大師之旅掌握最簡單,且最實用的教程。前言學習之道這本書使用路線圖中的精華部分用于傳授,并將其融入一個獨具吸引力的真實世界的具體代碼實現。完美展現了的優雅。膜拜的學習之道是必讀的一本書。 《React 學習之道》The Road to learn React (簡體中文版) 通往 React 實戰大師之旅:掌握 React 最簡單,且最實用的教程。 showIm...
摘要:初始化項目使用初始化項目安裝項目結構如下接口所有接口對封裝接下來對進行封裝,加上中間件實現類似于攔截器的效果。 Graphql嘗鮮 在只學習graphql client端知識的過程中,我們常常需要一個graphql ide來提示graphql語法,以及實現graphql的server端來進行練手。graphql社區提供了graphiql讓我們使用 graphiql (npm):一個交互...
摘要:區塊鏈最早出現在比特幣開元項目中。了不起的社會學實驗比特幣的誕生年化名中本聰的人發布比特幣白皮書,并在年公開了實現代碼比特幣的意義和價值比特幣首次真正從實踐意義上實現了安全可靠的去中心化數字貨幣機制。 區塊鏈最早出現在比特幣開元項目中。比特幣在誕生和發展過程中,借鑒了來自數字貨幣、密碼學、博弈論、分布式系統、控制論等多個領域的技術成果,作為核心支撐結構的區塊鏈技術大放異彩。 從實體貨幣...
閱讀 1865·2021-10-09 09:44
閱讀 3395·2021-09-28 09:35
閱讀 1385·2021-09-01 10:31
閱讀 1676·2019-08-30 15:55
閱讀 2718·2019-08-30 15:54
閱讀 939·2019-08-29 17:07
閱讀 1386·2019-08-29 15:04
閱讀 2012·2019-08-26 13:56