Начало работы с React+GraphQL

Node.js внешний интерфейс сервер GraphQL React.js
Начало работы с React+GraphQL

Я только недавно закончил новый проект, мне нечего делать, и я хочу научиться чему-то новому (все, кто работает на фронтенде, понимают, что обновление технологии слишком быстрое, легко выйти, если не научиться это), я слышал, чтоGraphQLСейчас он начинает работать, и он значительно заменит традиционныйRestful APIСпособ в тренде, вот и решил научиться.

Что такое GraphQL

GraphQL 是由 Facebook 创造的用于 API 的查询语言(这里查询语言所指的并不是常规意义上的类似 sql 语句的查询语言,而是一种用于前后端数据查询方式的规范)。

GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。

больше оGraphQLВы можете увидеть введениездесь

из-заGraphQLЭто всего лишь набор спецификаций, которые нельзя использовать напрямую, но сообщество реализовало множество языков программирования, которые можно использовать напрямую. Здесь я выбираюApollo.

Что такое Аполлон

Apollo 是基于 GraphQL 的全栈解决方案集合。包括了 apollo-client 和 apollo-server ;从后端到前端提供了对应的 lib 使得开发使用 GraphQL 更加的方便。

GraphQLЧтобы действительно играть свою роль, ему нужны передняя и задняя части.Сначала мы реализуем его на стороне сервера, который будет использоваться здесь.apollo-server.

apollo-serverэтоNode.jsосновываться наGraphQLПО промежуточного веб-сервера на стороне сервера. служба поддержкиexpress,koa,hapiи т.п. рама. Здесь я используюkoa.

Во-первых, нам нужно установить зависимости

yarn add koa koa-bodyparser koa-router apollo-server-koa graphql graphql-tools
//or
npm install koa koa-bodyparser koa-router apollo-server-koa graphql graphql-tools

Затем напишите код

// server.js

const Koa = require('koa');
const Body = require('koa-bodyparser');
const router = require('koa-router')();
const {graphqlKoa, graphiqlKoa} = require('apollo-server-koa');
const {makeExecutableSchema} = require('graphql-tools');
const { GraphQLScalarType } = require('graphql');
const { Kind } = require('graphql/language');

const app = new Koa();
const PORT = 8090;

// 模拟数据
const users = [
  {
    id: 1,
    name: 'J.K. Rowling',
    date: new Date(2018, 5, 20)
  },
  {
    id: 2,
    name: 'Michael Crichton',
    date: new Date(2018, 5, 21)
  },
];

const typeDefs = `
    scalar Date
    type User{
        id:Int!
        name:String!
        date: Date!
    }
    type Query {
        users(id:Int!): [User]
        user(id:Int!, name: String!):User
    }
    type Mutation {
        addUser(name:String!):User
    }
    schema {
        query: Query
        mutation: Mutation  
    }
`;

const resolvers = {
    Query: {    // 对应到typeDefs中的 type Query
        users(root, args, context) {
            return users;
        },
        user(root, args, context, info) {
          return {id: args.id, name: args.name};
      }
    },
    Mutation: { // 对应到typeDefs中的 Mutation
        addUser(root, args, context) {
            return {id: 2, name: args.name};
        }
    },
    Date: new GraphQLScalarType({ // 自定义标量类型
        name: 'Date',
        description: 'Date custom scalar type',
        parseValue(value) {
          return new Date(value); // 从客户端来的数据
        },
        serialize(value) {
          return value.getTime(); // 发送给客户端的数据
        },
        parseLiteral(ast) {
          if (ast.kind === Kind.INT) {
            return parseInt(ast.value, 10); 
          }
          return null;
        },
    }),
};


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

app.use(Body());

router.post('/graphql', graphqlKoa({
    schema: myGraphQLSchema,
}));
router.get('/graphql', graphqlKoa({
    schema: myGraphQLSchema,
}));

router.get( // 在浏览器里使用GraphiQL(可以理解成GraphQL领域的postman)
  '/graphiql',
  graphiqlKoa({
    endpointURL: '/graphql',
  }),
);

app.use(router.routes());
app.use(router.allowedMethods());
app.listen(PORT, ()=>console.log('app run in localhost:' + PORT));

Затем выполните следующую команду, чтобы запустить наш сервер:

node server.js
app run in localhost:8090

Затем введите в браузереhttp://localhost:8090/graphiql, вы увидите следующий интерфейс:

GraphiQL
Это объясняет нашуGraphQLСлужба запущена успешно. Вы можете выполнить соответствующий запрос данных в интерфейсе.

Сервер успешно запущен, и следующим шагом будет наш клиент.ReactФреймворк, для удобства проект использует его напрямуюcreate-react-appСоздайте.

После завершения создания заходим в директорию проекта, после чего устанавливаем клиентGraphQLЗапрос необходимых зависимостей:

yarn add react-apollo graphql-tag graphql apollo-client apollo-cache-inmemory apollo-link-http
// or
npm install react-apollo graphql-tag graphql apollo-client apollo-cache-inmemory apollo-link-http

Далее мы модифицируемsrc/index.jsкод в:

// src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { ApolloProvider } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';

const httpLink = new HttpLink({ uri: 'http://localhost:8090/graphql' })

const client = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache()
})

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>
, document.getElementById('root'));
registerServiceWorker();

затем изменитьsrc/App.jsкод в:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import gql from 'graphql-tag';
import { graphql } from 'react-apollo';

class App extends Component {
  render() {
    console.log(this.props);
    const { loading } = this.props.data;
    if (loading) {
      return <div>Loading...</div>
    }
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
        <p>{this.props.data.user.name}</p>
      </div>
    );
  }
}

export default graphql(gql`
  query User{
    user(id: 100, name: "zhangsfs") {
      id
      name
    }
    users(id: 100) {
      id
      name
      date
    }
  }
`)(App);

Часто обернутые компоненты приложения внедряются в файл с именемdataизprops, который содержит следующие поля:

data
где пользователь и пользователи — это поля, которые я запрашиваю, поэтому эти два поля не нужны. Кроме этого требуется все остальное, в том числеloadingПолеtrueзаключается в том, что он запрашивает, дляfalseУказывает, что запрос завершен.

Затем запустите код внешнего интерфейса:

yarn start
// Compiled successfully!
// You can now view client in the browser.

// Local:            http://localhost:8081/
// On Your Network:  http://172.22.228.1:8081/

Введите в браузереhttp://localhost:8081/Выяснилось, что страница сообщает об ошибке и не работает нормально, мы открыли инструменты разработчика и обнаружили одну из ошибок:

error
Как видно из поперечной проблемы с перекрестной доменной ошибкой, поскольку проект работает на двух разных портах, поскольку политика одинакового происхождения браузера, она не позволяет доступом к перекрестному домену.

Итак, как мы можем добиться междоменного доступа? Нам нужно изменить код на стороне сервера для поддержки междоменного доступа.

Сначала добавьте пакет зависимостей на стороне сервера:

yarn add @koa/cors@2

Затем измените код server.js:

// server.js

const Koa = require('koa');
const Body = require('koa-bodyparser');
const router = require('koa-router')();
const cors = require('@koa/cors');

...

app.use(Body());
app.use(cors());

...

app.listen(PORT, ()=>console.log('app run in localhost:' + PORT));

Затем перезапустите код сервера, обновитеhttp://localhost:8081/, обнаружил, что проект может работать нормально. Пока что простойGraphQLЗапрос завершен.

напиши в конце

Вышеупомянутое очень простоGraphQLПроверьте демо, потому что я тоже новичок, и многие вещи все еще находятся в стадии изучения. Если у вас есть хороший опыт разработки, добро пожаловать на обмен.