GraphQL鎺ュ彛寮€鍙戝揩閫熷叆闂細鍛婂埆杩囧害鑾峰彇涓庝笉瓒宠幏鍙栫殑鏃朵唬
鍦ㄤ紶缁熺殑RESTful API寮€鍙戜腑锛屼綘鏄惁鏇鹃亣鍒拌繃杩欐牱鐨勫洶鎵帮細涓轰簡鑾峰彇涓€涓敤鎴风殑鍩烘湰淇℃伅鍙婂叾鏈€杩戠殑涓夌瘒鏂囩珷锛屼綘闇€瑕佸厛璋冪敤`/users/{id}`鎺ュ彛鑾峰彇鐢ㄦ埛淇℃伅锛岀劧鍚庡啀璋冪敤`/users/{id}/posts?limit=3`鑾峰彇鏂囩珷淇℃伅锛熸垨鑰呮洿绯熺硶鐨勬槸锛屽悗绔彁渚涗簡涓€涓€滃叏鑳解€濇帴鍙o紝杩斿洖浜嗗ぇ閲忎綘涓嶉渶瑕佺殑瀛楁鏁版嵁锛岄€犳垚浜嗙綉缁滆祫婧愮殑娴垂锛?
杩欏氨鏄疓raphQL瑕佽В鍐崇殑鏍稿績闂銆?
浠€涔堟槸GraphQL锛?
GraphQL鏄疐acebook浜?015骞村紑婧愮殑涓€绉岮PI鏌ヨ璇█鍜岃繍琛屾椂鐜銆傚畠涓嶆槸鏁版嵁搴撴煡璇㈣瑷€锛岃€屾槸API鏌ヨ璇█銆備笌RESTful API涓嶅悓锛孏raphQL鍏佽瀹㈡埛绔簿纭寚瀹氶渶瑕佺殑鏁版嵁缁撴瀯鍜屽瓧娈碉紝鏈嶅姟鍣ㄥ垯杩斿洖涓庤姹傚畬鍏ㄥ尮閰嶇殑鏁版嵁锛屼笉澶氫笉灏戙€?
GraphQL鐨勬牳蹇冧紭鍔?
1. 绮剧‘鑾峰彇鏁版嵁锛氬鎴风鍙互绮剧‘鎸囧畾闇€瑕佸摢浜涘瓧娈碉紝閬垮厤杩囧害鑾峰彇鎴栦笉瓒宠幏鍙?
2. 鍗曚竴绔偣锛氭墍鏈夎姹傞兘鍙戦€佸埌鍚屼竴涓鐐癸紝绠€鍖栦簡API绠$悊
3. 寮虹被鍨嬬郴缁燂細GraphQL Schema鎻愪緵浜嗘槑纭殑绫诲瀷瀹氫箟锛屼究浜庡伐鍏烽摼鏀寔鍜岀被鍨嬫鏌?
4. 瀹炴椂鏁版嵁鏀寔锛氶€氳繃璁㈤槄(subscriptions)鏀寔瀹炴椂鏁版嵁鏇存柊
GraphQL鏍稿績姒傚康
1. Schema锛堟ā寮忥級
Schema鏄疓raphQL API鐨勬牳蹇冿紝瀹冨畾涔変簡API鐨勭被鍨嬬郴缁熷拰鑳藉姏銆係chema鐢辩被鍨嬪畾涔夌粍鎴愶紝鍏朵腑鏈€閲嶈鐨勬槸Query锛堟煡璇級銆丮utation锛堝彉鏇达級鍜孲ubscription锛堣闃咃級銆?
```graphql
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
type Query {
user(id: ID!): User
posts(limit: Int): [Post!]!
}
type Mutation {
createPost(title: String!, content: String!): Post!
}
```
2. Resolver锛堣В鏋愬櫒锛?
瑙f瀽鍣ㄦ槸瀹為檯鎵ц鏁版嵁鑾峰彇閫昏緫鐨勫嚱鏁般€傛瘡涓瓧娈甸兘鏈変竴涓搴旂殑瑙f瀽鍣ㄣ€?
```javascript
const resolvers = {
Query: {
user: (parent, args, context, info) => {
return getUserById(args.id);
},
posts: (parent, args, context, info) => {
return getPosts(args.limit || 10);
}
},
User: {
posts: (parent, args, context, info) => {
return getPostsByUserId(parent.id);
}
}
};
```
3. Query锛堟煡璇級
鏌ヨ鐢ㄤ簬鑾峰彇鏁版嵁锛岀被浼间簬RESTful API涓殑GET璇锋眰銆?
```graphql
query GetUserWithPosts($userId: ID!) {
user(id: $userId) {
id
name
email
posts(limit: 3) {
id
title
content
}
}
}
```
4. Mutation锛堝彉鏇达級
鍙樻洿鐢ㄤ簬淇敼鏁版嵁锛岀被浼间簬RESTful API涓殑POST銆丳UT銆丏ELETE璇锋眰銆?
```graphql
mutation CreatePost($title: String!, $content: String!) {
createPost(title: $title, content: $content) {
id
title
content
author {
id
name
}
}
}
```
蹇€熷疄璺碉細鏋勫缓涓€涓畝鍗曠殑GraphQL API
璁╂垜浠娇鐢∟ode.js鍜孉pollo Server蹇€熸瀯寤轰竴涓畝鍗曠殑GraphQL API銆?
姝ラ1锛氬垵濮嬪寲椤圭洰
```bash
mkdir graphql-api
cd graphql-api
npm init -y
npm install apollo-server graphql
```
姝ラ2锛氬垱寤哄熀纭€Schema鍜岃В鏋愬櫒
```javascript
// index.js
const { ApolloServer, gql } = require('apollo-server');
// 妯℃嫙鏁版嵁
const users = [
{ id: '1', name: '寮犱笁', email: 'zhangsan@example.com' },
{ id: '2', name: '鏉庡洓', email: 'lisi@example.com' }
];
const posts = [
{ id: '1', title: 'GraphQL鍏ラ棬', content: 'GraphQL鏄竴绉嶅己澶х殑API鏌ヨ璇█', authorId: '1' },
{ id: '2', title: 'Node.js杩涢樁', content: '娣卞叆瀛︿範Node.js鐨勬牳蹇冩蹇?, authorId: '1' },
{ id: '3', title: '鍓嶇寮€鍙戣秼鍔?, content: '2023骞村墠绔紑鍙戠殑鏂拌秼鍔?, authorId: '2' }
];
// 瀹氫箟Schema
const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
type Query {
users: [User!]!
user(id: ID!): User
posts: [Post!]!
post(id: ID!): Post
}
type Mutation {
createUser(name: String!, email: String!): User!
createPost(title: String!, content: String!, authorId: ID!): Post!
}
`;
// 瀹氫箟瑙f瀽鍣?
const resolvers = {
Query: {
users: () => users,
user: (parent, args) => users.find(user => user.id === args.id),
posts: () => posts,
post: (parent, args) => posts.find(post => post.id === args.id)
},
User: {
posts: (parent) => posts.filter(post => post.authorId === parent.id)
},
Post: {
author: (parent) => users.find(user => user.id === parent.authorId)
},
Mutation: {
createUser: (parent, args) => {
const newUser = {
id: String(users.length + 1),
name: args.name,
email: args.email
};
users.push(newUser);
return newUser;
},
createPost: (parent, args) => {
const newPost = {
id: String(posts.length + 1),
title: args.title,
content: args.content,
authorId: args.authorId
};
posts.push(newPost);
return newPost;
}
}
};
// 鍒涘缓Apollo Server瀹炰緥
const server = new ApolloServer({
typeDefs,
resolvers
});
// 鍚姩鏈嶅姟鍣?
server.listen().then(({ url }) => {
console.log(`馃殌 Server ready at ${url}`);
});
```
姝ラ3锛氳繍琛屽苟娴嬭瘯API
```bash
node index.js
```
璁块棶 http://localhost:4000 鍗冲彲鎵撳紑GraphQL Playground锛岃繖鏄竴涓氦浜掑紡鐨凣raphQL IDE銆?
姝ラ4锛氭墽琛屾煡璇?
鍦≒layground涓皾璇曚互涓嬫煡璇細
```graphql
query GetUsersWithPosts {
users {
id
name
posts {
id
title
}
}
}
```
鎴栬€呭皾璇曞彉鏇存搷浣滐細
```graphql
mutation CreateNewPost {
createPost(
title: "GraphQL瀹炴垬"
content: "閫氳繃瀹為檯妗堜緥瀛︿範GraphQL"
authorId: "1"
) {
id
title
content
author {
name
}
}
}
```
GraphQL鏈€浣冲疄璺?
1. 鍚堢悊璁捐Schema锛氫粠涓氬姟闇€姹傚嚭鍙戯紝璁捐鍚堢悊鐨勭被鍨嬪拰鍏崇郴
2. 閬垮厤N+1鏌ヨ闂锛氫娇鐢―ataLoader绛夊伐鍏锋壒閲忓姞杞藉叧鑱旀暟鎹?
3. 瀹炴柦鏉冮檺鎺у埗锛氬湪瑙f瀽鍣ㄤ腑鍔犲叆璁よ瘉鍜屾巿鏉冮€昏緫
4. 鎬ц兘鐩戞帶锛氱洃鎺ф煡璇㈡€ц兘鍜屽鏉傚害锛岄槻姝㈡伓鎰忓鏉傛煡璇?
5. 鐗堟湰绠$悊锛氶€氳繃娓愯繘寮廠chema婕旇繘鑰岄潪鐗堟湰鍙风鐞咥PI鍙樻洿
GraphQL vs REST锛氫綍鏃堕€夋嫨锛?
閫夋嫨GraphQL褰擄細
- 闇€瑕佺伒娲荤殑鏁版嵁鑾峰彇锛岄伩鍏嶈繃搴﹁幏鍙栨垨涓嶈冻鑾峰彇
- 鍓嶇闇€姹傚鍙橈紝闇€瑕佸揩閫熻凯浠?
- 闇€瑕佸噺灏戠綉缁滆姹傛鏁?
- 闇€瑕佸己绫诲瀷API鍜岃嚜鍔ㄦ枃妗g敓鎴?
閫夋嫨REST褰擄細
- API缁撴瀯绠€鍗曞浐瀹?
- 闇€瑕佸埄鐢℉TTP缂撳瓨鏈哄埗
- 椤圭洰鍥㈤槦瀵筊EST鏇寸啛鎮?
- 闇€瑕佺畝鍗曠殑鏂囦欢涓婁紶绛夋搷浣?
鎬荤粨
GraphQL浠h〃浜咥PI璁捐鐨勬柊鑼冨紡锛屽畠閫氳繃璧嬩簣瀹㈡埛绔簿纭帶鍒舵暟鎹殑鑳藉姏锛岃В鍐充簡浼犵粺RESTful API鐨勮澶氱棝鐐广€傝櫧鐒跺涔犳洸绾跨浉瀵归櫋宄紝浣嗕竴鏃︽帉鎻★紝瀹冨皢鏋佸ぇ鍦版彁鍗囧墠鍚庣鍗忎綔鏁堢巼鍜岀敤鎴蜂綋楠屻€?
鏃犺浣犳槸鍓嶇寮€鍙戣€呭笇鏈涜幏寰楁洿鐏垫椿鐨勬暟鎹幏鍙栬兘鍔涳紝杩樻槸鍚庣寮€鍙戣€呭笇鏈涙瀯寤烘洿楂樻晥鐨凙PI锛孏raphQL閮藉€煎緱浣犳姇鍏ユ椂闂村涔犮€備粠浠婂ぉ寮€濮嬶紝灏濊瘯鍦ㄤ綘鐨勪笅涓€涓」鐩腑寮曞叆GraphQL锛屼綋楠屽畠甯︽潵鐨勫彉闈╁惂锛?
璁颁綇锛屾妧鏈€夊瀷姘歌繙鏈嶅姟浜庝笟鍔¢渶姹傘€侴raphQL涓嶆槸閾跺脊锛屼絾鍦ㄥ悎閫傜殑鍦烘櫙涓嬶紝瀹冪‘瀹炶兘甯︽潵鏄捐憲鐨勬晥鐜囨彁鍗囥€?