Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst...

56
Удобные API с GraphQL

Transcript of Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst...

Page 1: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Удобные API сGraphQL

Page 2: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Михаил Новиковtwitter.com/freiksenet

CTO @ Reindex

Page 3: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Современныеприложения

Page 4: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment
Page 5: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment
Page 6: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

{ id: "1", url: "some-url.jpg", createdAt: "2016-05-26T18:00:00", likes: 755, author: { id: "2", username: "mikkelerbeer", displayName: "Mikkeler", }, comments: [ { id: "3", content: "LIU XIAODONG", createdAt: "2016-05-26T18:05:00", author: { username: "mikkelerbeer", displayName: "Mikkeler", }, }, ],}

Page 7: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

id: "1",url: "some-url.jpg",createdAt: "2016-05-26T18:00:00",likes: 755,

author: { id: "2", username: "mikkelerbeer", displayName: "Mikkeler",},

{ id: "3", content: "LIU XIAODONG", createdAt: "2016-05-26T18:05:00", author: { username: "mikkelerbeer", displayName: "Mikkeler", },},

Page 8: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Хороший бакендОтдает данные быстро

Удобен для разработчика

Page 9: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

REST

Page 10: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Каноничный RESTОдин ресурс - один тип данныхid или url связанных обьектов

Page 11: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Каноничный RESTconst picture = await fetch('/picture/1');picture.author = await fetch(`/author/${picture.author}`);picture.comments = await fetch('/picture/1/comments');picture.comments = await Promise.all( picture.comments.map((comment) => ({ ...comment, author: await fetch(`/author/${comment.author}`) })));

Page 12: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Каноничный RESTОчень много запросовАбсолютно не практичен

Page 13: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Вложенный RESTОтдаем данные которые нужны

Толстые ресурсыМного ресурсов

Page 14: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Вложенный RESTЗаточен под вьюшкуПроблемы с reuse

Page 15: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Настраиваемый RESTconst picture = await fetch( '/picture/1?include=author,comments,comments.author');

Page 16: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

НастраиваемыйREST

Много работыМожет превратится в легаси

Page 17: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

REST этофилософия

Page 18: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

REST не идеалендля приложений

Page 19: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Что естьидеальныйбакенд?

Выбор нужных данныхПросто имплементировать

Отдает метаданные

Page 20: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

GraphQL

Page 21: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

GraphQL - языкзапросов

Page 22: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

{ id: "1", url: "some-url.jpg", createdAt: "2016-05-26T18:00:00", likes: 755, author: { id: "2", username: "mikkelerbeer", displayName: "Mikkeler", }, comments: [ { id: "3", content: "LIU XIAODONG", createdAt: "2016-05-26T18:05:00", author: { id: "2", username: "mikkelerbeer", displayName: "Mikkeler", }, }, ],}

Page 23: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

{ pictureById(id: "1") { id url createdAt likes author { id username displayName }, comments { id content createdAt author { username displayName } } }}

Page 24: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

GraphQL - сервер

Page 25: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Связанные типы с полями

Page 26: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

type User { id: ID! username: String displayName: String pictures: [Picture] comments: [Comment]}

type Picture { id: ID! url: String! author: User! comments: [Comment]}

type Comment { id: ID! author: User! picture: Picture! content: String!}

Page 27: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Поля могут принимать аргументы

Page 28: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

{ authorById(id: "1") { id avatar(size: MEDIUM) { url } pictures(limit: 10) { id url } }}

Page 29: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

GraphQL -метаданные

Page 30: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

GraphQL -идеальный бакенддля продуктов

Page 31: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Relay

Page 32: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Компоненты вместе и с ихданными

Page 33: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment
Page 34: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

const CommentContainer = Relay.createContainer(Comment, { fragments: { comment: () => Relay.QL` fragment on Comment { id text createdAt author { username displayName } } `, },});

Page 35: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

const PictureContainer = Relay.createContainer(Comment, { fragments: { picture: () => Relay.QL` fragment on Picture { id url createdAt likes author { ${AuthorPanel.getFragment('user')} } comments { ${Comment.getFragment('comment')} } } `, },});

Page 36: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

RelayМеньше бойлерплейта

Клиентский кешPagination

Оптимистичные мутации

Page 37: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

GraphQLэкосистема

GraphiQLApollo

HorizonReindex ;)

Page 38: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Как писать GraphQLбакенды

Page 39: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

graphql-js

Page 40: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Типизированная схема

Page 41: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

const Picture = new GraphQLObjectType({ name: 'Picture', fields: () => ({ id: { type: new GraphQLNonNull(GraphQLID), }, url: { type: GraphQLString, }, author: { type: User, }, comments: { type: new GraphQLList(Picture), }, }),});

Page 42: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

const Query = new GraphQLObjectType({ name: 'Query', fields: () => ({ pictureById: { type: Picture, }, }),});

Page 43: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Данные подключаются черезresolve методы

Page 44: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

const Query = new GraphQLObjectType({ name: 'Query', fields: () => ({ pictureById: { type: Picture, resolve() { id: "1", url: "some-url.jpg", author: { ... }, comments: [ ... ], } }, }),});

Page 45: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

resolve берет любой Promise

Page 46: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

const Query = new GraphQLObjectType({ name: 'Query', fields: () => ({ pictureById: { type: Picture, resolve(parent, { id }) { return db.collection('Picture').find({ _id: id }); } }, }),});

Page 47: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

resolve можно подключить клюбому полю

Page 48: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

const Picture = new GraphQLObjectType({ name: 'Picture', fields: () => ({ ..., author: { type: User, resolve(parent) { return db.collection('User').find({ _id: parent.author }); } }, }),});

Page 49: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

GraphQL как APIgateway

Page 50: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

const Picture = new GraphQLObjectType({ name: 'Picture', fields: () => ({ ..., comments: { type: new GraphQLList(Picture), resolve(parent) { return fetch( `/third-party/comments/${parent.commentId}` ); }, }, }),});

Page 51: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Производительность

Page 52: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

{ pictureById(id: "1") { id url createdAt likes author { id username displayName }, comments { id content createdAt author { username displayName } } }}

Page 53: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

ПроизводительностьN+1 problemБэтчинг

Анализ запросов

Page 54: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Будущее GraphQL

Page 55: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

НедостаткиGraphQL

Page 56: Удобные API с GraphQLpublic.jugru.org/holyjs/2016/spb/day_1/track_2/novikov.pdfconst PictureContainer = Relay.createContainer(Comment, {fragments: {picture: => Relay.QL` fragment

Use GraphQL ;)