開始使用GraphQL

爲何要用graphql?

讓咱們先回顧一下咱們如今所使用的API設計風格css

純rest:一個endpoint對應一個資源

優勢:靈活、解構
缺點:因爲一個endpoint對應一個資源因此須要不少次請求html

類rest:一個endpoint對應一個視圖

優勢:一次請求、所得即所需
缺點:不夠靈活、高度耦合、很高的維護成本、迭代慢前端

上面是咱們兩種經常使用的接口方式,兩種都有各自的優缺點,有沒有能夠包攬全部優勢的方案呢?咱們須要一個標準的API層,那這就是GraphQL,請注意GraphQL是一個規範,是由facebook倡導的一個規範,不是一個實現。
GraphQL有下面三個定義:node

  1. 一個用來描述數據類型和關係的API定義語言
  2. 一個能夠描述具體須要獲取哪些數據的查詢語言
  3. 一個能夠resolve到數據單個屬性的可執行模型

GraphQL是長什麼樣子的呢?
圖片描述react

可能這樣看起來還比較難理解,沒事,咱們直接coding。git

GraphQL實踐

因爲GraphQL是一種規範,它不是一種實現,若是要本身實現仍是比較難的,不用擔憂,強大的開源社區已經幫咱們準備好了,這就是Apollo開源項目。Apollo提供了豐富的後端實現(node支持:express、koa、hapi、restify等框架)和前端(React、RN、Angular、IOS、Android等)實現。官方文檔:http://dev.apollodata.com/too...。下面的實踐都是基於Apollo以nodejs的Express框架來實現的。
Demo代碼:https://github.com/jasondu/ap...github

1、如何搭建GraphQL服務端

步驟

  1. 搭建服務器

import express from 'express';
import { 
  graphqlExpress, 
  graphiqlExpress, 
} from 'apollo-server-express';
import bodyParser from 'body-parser';
import schema from './data/schema';    // 定義GraphQL查詢格式

const GRAPHQL_PORT = 3002;

const graphQLServer = express();

graphQLServer.use('/graphql', bodyParser.json(), graphqlExpress({ schema }));    // 實現GraphQL接口功能
graphQLServer.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));    // 實現GraphQL瀏覽器調試界面

graphQLServer.listen(GRAPHQL_PORT, () => console.log(
  `GraphiQL is now running on http://localhost:${GRAPHQL_PORT}/graphiql`
));

懂Express的童鞋應該均可以看到上面的代碼,我作一下解釋:數據庫

  • apollo-server-express 是由Apollo提供在express環境下實現grapql的庫,這裏使用了裏面兩個類
  • graphqlExpress是實現grapql接口功能的類
  • graphiqlExpress是實現grapql瀏覽器調試界面(An in-browser IDE for exploring GraphQL.)的類,就多了一個「i」,這個調試界面能夠在後面看到
  • schema就是上文講的是定義GraphQL查詢格式的
  1. 編寫Schema

    讓咱們看看Schema.js是怎麼寫的express

import {
  makeExecutableSchema,
} from 'graphql-tools';
import resolvers from './resolvers';

// 定義schema
const typeDefs = `
type Author {   # 做者的字段有:id,名字,還有 發表的帖子
  id: Int
  firstName: String
  lastName: String
  posts: [Post]
}
type Post {    # 帖子的字段有下面這些,包括 這個帖子是哪一個做者寫的
  id: Int
  title: String
  text: String
  views: Int
  author: Author
}
type Query {    # 定義查詢內容
  author(firstName: String, lastName: String): Author # 查詢做者信息
  getFortuneCookie: String
}
`;

const schema = makeExecutableSchema({ typeDefs, resolvers });

export default schema;

這裏用到Apollo提供的makeExecutableSchema方法,這個方法是將Schema結構的數據轉換成GraphQLSchema實例。
typeDefs裏面定義了三個格式Author,Post,Query,這裏Query就是查詢的時候返回的結構,Author,Post是解釋了在Query中的結構類型。
接下來,咱們就能夠編寫具體的實現了。npm

  1. 編寫Resolvers

const resolvers = {
  Query: {
    author(root, args){    // args就是上面schema中author的入參
      return { id: 1, firstName: 'Hello', lastName: 'World' };
    },
  },
  Author: {
    // 定義author中的posts
    posts(author){
      return [
        { id: 1, title: 'A post', text: 'Some text', views: 2},
        { id: 2, title: 'Another post', text: 'Some other text', views: 200}
      ];
    },
  },
  Post: {
    // 定義Post裏面的author
    author(post){
      return { id: 1, firstName: 'Hello', lastName: 'World' };
    },
  },
};

export default resolvers;

上面這段代碼比較簡單,就不作解釋了。
至此,咱們就完成了一個GraphQL服務端的開發,加下來咱們npm i & npm start
圖片描述
吶,這樣就啓動啦!打開http://localhost:3002/graphiql就能夠看到剛纔前面說的graphiql,就是GraphQL瀏覽器調試界面。

graphiql能夠支持聯想功能,能夠很是快的書寫查詢語句。
Tb8cIS3jlC.gif

2、如何在客戶端查詢GraphQL數據(以react爲例)

步驟

  1. 使用create-react-app建立一個項目,而且按照Apollo客戶端解決方案庫:react-apollo

create-react-app client & yarn add react-apollo
  1. 修改App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

// -------- 添加內容 -------- //
import {
  ApolloClient,
  ApolloProvider,
  createNetworkInterface,
  gql,
  graphql,
} from 'react-apollo';

// 設置接口地址
const networkInterface = createNetworkInterface({ uri: 'http://localhost:3002/graphql' });

const client = new ApolloClient({
  networkInterface,
});

const Test = ({ data: { loading, error, author } }) => {
  if (loading) {
    return <p>Loading ...</p>;
  }
  if (error) {
    return <p>{error.message}</p>;
  }

  return (
    <h3>{author.firstName} {author.lastName}</h3>
  );
};
// 查詢語句
const query = gql`
  query AuthorQuery {
    author (firstName: "firstName", lastName: "lastName") {
      firstName,
      lastName
    }
  }
`;

const Gtest = graphql(query)(Test);

// -------- 添加內容 -------- //

class App extends Component {
  render() {
    return (
      <ApolloProvider client={client}>
        <div className="App">
          <div className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <Gtest />
          </div>
          <p className="App-intro">
            To get started, edit <code>src/App.js</code> and save to reload.
        </p>
        </div>
      </ApolloProvider>
    );
  }
}


export default App;

這裏的寫法跟redux相似,使用<ApolloProvider>包裹項目,經過graphql方法將數據注入到組件中。

而後執行yarn start 這樣項目就啓動了,以下圖

注:這裏存在跨域問題,因此服務器端須要使用cors解決跨域問題,具體看代碼。

下面是我收集的相關學習資料:

https://dev-blog.apollodata.c...

《Tutorial: How to build a GraphQL server》講解了如何搭建node GraphQL服務器,如何定義schema,還有如何連接之前的SQL數據庫,rest等,入門必讀

https://dev-blog.apollodata.c...

《Full-stack React + GraphQL Tutorial》講解如何和客戶端結合起來,還有若是實現ws實時通訊等

https://launchpad.graphql.com...

這個是apollo提供的線上編輯器,能夠在線上編寫schema和resolve,而後能夠下載下來部署

https://www.howtographql.com/

這個網站詳細講解了如何在各類服務器客戶端使用graphql

http://taobaofed.org/blog/201...

《Node.js 服務端實踐之 GraphQL 初探》阿里在15年寫的文章

http://graphql.org/官網

相關文章
相關標籤/搜索