Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GraphQL - уменьшаем энтропию

Polina Gurtovaya
September 07, 2019
520

GraphQL - уменьшаем энтропию

Рассказ о том как GraphQL помогаем упрощать сложные проекты

Polina Gurtovaya

September 07, 2019
Tweet

Transcript

  1. !2

  2. !3

  3. !4

  4. !12 { "showcase": { "name": “ebay.de", "siteCode": “DE" } }

    { "showcase": { "name": “ebay.com", "site": { "code": “US" } } } Беспорядок в данных
  5. Overfetching / Underfetching !13 { "showcase": { "name": "ebay.com", "active":

    true, "id": "92", "primary": true, "currency": "USD", "site": { "code": "US", "name": "ebay.com", "currency": "USD", "country": "US", "domain": "ebay.com" } } } <Site name={site.name} code={site.code} />
  6. Недостаточно информации !15 // lodash get(obj, "showcase.site.code"); // ramda path(["showcase",

    "site", "code"], obj); showcase?.site?.code { "showcase": { "name": “ebay.au", "site": null } } <Flag code={showcase.site.code} />
  7. Что у нас было? !17 Беспорядок в данных Overfetching /

    Underfetching Нет уверенности в данных Лишние сущности Простой код Минимум сущностей Легкое общение
  8. Operation Schema !20 query { viewer { id name }

    product(id: 5) { title quantity tags } } type Query { viewer: User product(id: ID!): Product … } type Product { title: String quantity: Float! tags: [String] user: User … } Operation Type Fileds Selection Set Input type Output type Wrapper type Object type Scalar type
  9. Unions !21 { info { id ... on User {

    name } ... on Product { title } } } union UserOrProduct = User | Product type Query { info: UserOrProduct } type User { id: ID! name: String } type Product { id: ID! title: String }
  10. Interfaces !22 { info { id ... on User {

    name } ... on Product { title } } } interface Node = { id: ID! } type Product implements Node { id: ID! title: String } type User implements Node { id: ID! name: String } type Query { info: Node }
  11. !23 query { viewer { email name id } product(id:

    5) { title quantity users { email name id } } } Фрагменты query { viewer { ...UserInfo } product(id: 5) { title quantity users { ...UserInfo } } } fragment UserInfo on User { email name id }
  12. !24 Фрагменты мёржатся fragment UserInfo on User { id email

    name } fragment UserStatus on User { id name online } query { viewer { ...UserInfo ...UserStatus } } "data": { "viewer": { "id": 1, "name": "zloymult", "email": “[email protected]”, "online": true } }
  13. Execution !25 query { product(id: 5) { title user {

    name id } } } Рекурсивно обходим наш граф и выполняем каждое поле { Query: { product: (_, { id }) => ({ id, title: `Product${id}`, user: { id: 1 } }) }, User: { name: ({ id }) => `User${id}` } }
  14. Интроспекция !26 { __schema { directives { name } }

    __type(name: "Query"){ fields { name description } } } { "data": { "__schema": { "directives": [ … { "name": "deprecated" } ] }, "__type": { "fields": [ { "name": "address", "description": "Get seller’s …" }, …
  15. Стало лучше !28 Беспорядок в данных Overfetching / Underfetching Нет

    информации о данных Лишние сущности Простой код Минимум сущностей Легкое общение
  16. GraphQL мапит бизнес-логику !30 query { product(id: 5) { title

    quantity } } "data": { "product": { "title": "", "quantity": 112 } }
  17. !32 Operation-Based Fragment-based Отличные доки Хорошие доки Не всегда нужна

    схема Нужна схема React, RN, Vue, Angular …. React, RN Свой компилятор Развивается быстрее Больше оптимизаций из коробки Есть GC
  18. !33 query GetViewer { viewer { id currency } }

    <UserInfo name={props.name}/> Normalized Cache { "data": { "viewer": { "id": "1", "currency": "CAD", } } }
  19. !34 <UserInfo name={props.name}/> { "data": { "viewer": { "id": "1",

    "currency": "CAD", } } } Normalized Cache query GetViewer { viewer { id currency } }
  20. Normalized cache (Apollo case) !35 query { viewer { id

    currency accounts { id name } } } query { viewer { id currency __typename accounts { id name __typename } } } { "data": { "viewer": { "id": "1", "currency": "CAD", "__typename": "User", "accounts": [ { "id": "5", "name": “John Doe”, "__typename": "Account" } ] } } }
  21. { "data": { "viewer": { "id": "1", "currency": "CAD", "__typename":

    "User", "accounts": [ { "id": “5", "name": “John Doe”, "__typename": "Account" } ] } } } Normalized cache (Writing) !36 "id": "1", "currency": "CAD", "__typename": "User", "accounts": […] "id": “5", "name": “John Doe”, "__typename": "Account" User:1 Account:5
  22. mutation { updateViewer(currency: "USD") { viewer { id currency __typename

    } } } Normalized cache (Rewriting) !37 { "data": { “updateViewer" { "viewer": { "id": "1", "currency": "USD" “__typename”: "User" } } } } "USD" User:1 "id": "1", "currency": "CAD", "__typename": "User", "accounts": […] Account:5 "id": “5", "name": “John Doe”, "__typename": "Account" "USD"
  23. Code example !38 # viewerInfo.graphql query ViewerInfo { viewer {

    id currency } } // ViewerSettings.js import { useQuery } from '@apollo/react-hooks'; import { ViewerInfo } from './viewerInfo.graphql'; export function ViewerSettings() { const { loading, data } = useQuery(ViewerInfo); return ( <div> {loading ? <p>Loading</p> : <p>Currency: {data.viewer.currency}</p>} </div> ); }
  24. Успех! !39 Беспорядок в данных Overfetching/Underfetching Нет информации о данных

    Лишние сущности Простой код Минимум сущностей Легкое общение
  25. В интернетах пишут что GraphQL это плохо !42 Это все

    ужасно не гибко! GraphQL ломает кеширование. Какое именно? GraphQL запросы слишком большие! Ага. Но есть persisted queries GraphQL запросы тормозят БД! Иногда такое бывает. Это решаемо Apollo это плохо! Apollo != GraphQL :) Возможно это к лучшему :) ts тоже не гибко