Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Nikita Galkin "Looking for the right tech stack for GraphQL application"

139 views

Published on

У рамках доповіді ми будемо говорити про реалізації серверної частини GraphQL додатку. Тобто доповідь орієнтована в першу чергу на Node.js розробників. Проте концепції з доповіді можуть бути реалізовані на інших серверних платформах. Ми обговоримо такі питання та варіанти їх вирішення:

дублювання в GraphQL схемі та коді, а так же ризик їх розсинхронізації;
тестування та версіонування GraphQL схеми й додатку;
авторизація та перевірка прав доступа до полів та мутаторів;
продуктивність;
підписки;
реалізація фронтенд компонентів з GraphQL як джерелом даних.
Для слухачів, які не мають досвіду з GraphQL рекомендується ознайомитися з інформацією .

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Nikita Galkin "Looking for the right tech stack for GraphQL application"

  1. 1. Looking for the right tech stack for GraphQL application Nikita Galkin
  2. 2. Nikita Galkin Love and Know: ▰ How to make developers and business happy ▰ Technical and process debt elimination Believe that: ▰ Any problem must be solved at the right level ▰ Software is easy. People are hard ▰ A problem should be highlighted, an idea should be "sold", a solution should be demonstrated Links: Site GitHub Twitter Facebook 2
  3. 3. GraphQL is an open source query language created by Facebook The specification published in June 2018
  4. 4. What problems does GraphQL solve?
  5. 5. Client Development is too expensive
  6. 6. Ask for what you need, get exactly that
  7. 7. Domain knowledge does not represent at a single place as source code
  8. 8. By Dmytro Naumenko
  9. 9. Describe what’s possible with a type system
  10. 10. It is complicated to develop Server and Client in parallel
  11. 11. GraphQL is awesome!
  12. 12. GraphQL is awesome!
  13. 13. But… with GraphQL Server Development becomes much harder
  14. 14. My story: Node.js and GraphQL during 1 year and 4 projects
  15. 15. Honeymoon with GraphQL: ● Reading docs ● Exploring how to GraphQL ● Comparing Apollo, Prisma, Relay, etc ● Choosing IDE
  16. 16. GraphiQL
  17. 17. GraphQL Playground
  18. 18. Insomnia
  19. 19. GraphQL Schema Definition Language: ● A type has a name and can implement one or more interfaces ● A field has a name and a type ● The built-in scalar types are Int/Float/String/Boolean/ID ● Enum is a scalar value that has a specified set of possible values
  20. 20. I love to look in the mirrors Worse than D.R.Y., DUPLICATION at: ● Schema ● DB tables ● Endpoints Common solution: ● Schema generation
  21. 21. GraphQL at Facebook by Adam D.I. Kramer
  22. 22. { __schema { types { __typename name } } } Introspection query Class reflections JavaScript have not Reflection
  23. 23. npm install: ● reflect-metadata ● typescript ● type-graphql ● any other useful decorators first packages
  24. 24. import { Field, ID, ObjectType } from 'type-graphql'; import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; @Entity({ name: 'users' }) @ObjectType() export class User { @PrimaryGeneratedColumn('uuid') @Field(type => ID) id: string; @Column() @Index({ unique: true }) @Field() email: string; @Column() passwordHash: string; @Column({ nullable: true }) @Field({ nullable: true }) firstName?: string; @Column({ nullable: true }) @Field({ nullable: true }) lastName?: string; @Field() get name () { return `${this.firstName} ${this.lastName}`; } }
  25. 25. import { Ctx, Query, Resolver } from 'type-graphql'; import { GraphQLContext } from '~/boundaries/graphql'; import { UsersRepository } from '~/repositories'; import { User } from '~/entities'; @Resolver(type => User) export class UserResolver { @Query(type => User) async currentUser ( @Ctx() context: GraphQLContext ): Promise<User> { return UsersRepository.find( { where: { id: context.user.id } }, ); } }
  26. 26. Documentation and examples: https://typegraphql.ml
  27. 27. I have Big Latency, perhaps Reasons: ● Poor Performance ● Too many DB queries ● Client cache only Common solution: ● Dataloader
  28. 28. Precomputed data You store data for resolvers in NoSQL DB with structure similar GraphQL schema. Limitations: ● You have data ownership
  29. 29. We need data, but there are not decorators for such source type. For example: ● Elastic Search ● Data from external API ● etc I miss something...
  30. 30. // class class User { constructor(name, surname) { this.name = name; this.surname = surname; } } // class instance new User('Bart', 'Simpson'); // plain (literal) object ==============> const hero = { name: 'Gomer', surname: 'Simpson' }; POM
  31. 31. import { plainToClass } from 'class-transformer'; fetch("users.json").then((users: Object[]) => { const realUsers = plainToClass(User, users); // now each user in realUsers is instance of User class }); const hero = { name: 'Gomer', surname: 'Simpson' }; hero instanceof User; // false
  32. 32. https://github.com/typestack/class-transformer Serialize/Deserialize on steroids with decorators: ● @Type ● @Expose ● @Exclude ● Use discriminator for arrays!
  33. 33. Reasons: ● SELECT all, because pagination and sorting implemented in the resolver ● SELECT * FROM ... ● JOIN is used I have Big Requests, Dear!
  34. 34. Precomputed Materialized View
  35. 35. Sorting, filtering and pagination should be implemented on Data Layer
  36. 36. GraphQL Resolver function signature: fieldName(obj, args, context, info) ● obj: The object that contains the result returned from the resolver on the parent field ● args: An object with the arguments passed into the field in the query ● context: This is an object shared by all resolvers ● info: AST, state of resolving. Example
  37. 37. import { GraphQLResolveInfo } from 'graphql'; import graphqlFields from 'graphql-fields'; import { Ctx, Info, Query, Resolver } from 'type-graphql'; import { GraphQLContext } from '~/boundaries/graphql'; import { UsersRepository } from '~/repositories'; import { User } from '~/entities'; @Resolver(type => User) export class UserResolver { @Query(type => User) async currentUser ( @Ctx() context: GraphQLContext, @Info() info: GraphQLResolveInfo ): Promise<User> { const fields = graphqlFields(info); return UsersRepository.find( { where: { id: context.user.id } }, { select: Object.keys(fields) } ); } }
  38. 38. import graphqlFields from 'graphql-fields'; // ... async currentUser ( @Ctx() context: GraphQLContext, @Info() info: GraphQLResolveInfo ): Promise<User> { const fields = graphqlFields(info); return UsersRepository.find( { where: { id: context.user.id } }, { select: Object.keys(fields) } ); }
  39. 39. ● ACL ● Query Complexity We have to talk about our relationship... import { Authorized } from 'type-graphql'; // ... @ObjectType() export class User { // ... @Authorized('Admin', 'CurrentUser') @Field() email: string; @Field(type => User,{ complexity: 20 }) friends: User[]; }
  40. 40. Solutions: ● For versioning graphql-doctor ● For CI/CD eslint-plugin-graphql ● For development WebStorm IDE plugin Let's not change anything?
  41. 41. Ideas: ● Have only one source of truth ● Don’t repeat yourself ● Use the right tools ● Solve problem at the right level
  42. 42. 47 THANKS! HAPPY CODING WITH GRAPHQL You can find me on Twitter as @galk_in Slides are available at speakerdeck.com/galkin or at my site galk.in

×