Slide 1

Slide 1 text

GraphQL Serverをつくる・つなぐ 2019/12/18 FROKAN × UIT #2 @spring_raining

Slide 2

Slide 2 text

About Me • Tamada Akihiro • Twitter: spring_raining / GitHub: spring-raining • フロントエンドエンジニア at LINE株式会社 UIT • 普段はLINE公式アカウントを担当 Follow me! >

Slide 3

Slide 3 text

Agenda • 新規社内サービス立ち上げとGraphQLに出会うまで • GraphQL Serverをつくる • GraphQL Serverをつなぐ

Slide 4

Slide 4 text

LINE Design System (LDS) • LINEファミリーアプリ横断で用いる次世代のデザインシステム • #linedevday でたくさん情報が出てます LINEのデザインシステム:一貫性を損なうことなくLINEのサービスの速度を上げる
 https://linedevday.linecorp.com/jp/2019/sessions/A2-2 デザインシステムにおけるフロントエンド https://linedevday.linecorp.com/jp/2019/sessions/A2-3

Slide 5

Slide 5 text

https://linedevday.linecorp.com/jp/2019/sessions/A2-2

Slide 6

Slide 6 text

https://linedevday.linecorp.com/jp/2019/sessions/A2-2

Slide 7

Slide 7 text

アイコン管理ツール LAICON • LINE社内のアイコン資産を共有するFont Awesome的なやつ • LDSに合わせてトーンを統一したアイコンにリニューアル中

Slide 8

Slide 8 text

宣伝っぽい導入終了

Slide 9

Slide 9 text

現状の問題点 • LAICONのリリースにエンジニアが関与しなければならない • ValidなSVGかチェック • アイコンの命名 • アイコンフォントのビルド・デプロイ

Slide 10

Slide 10 text

LAICON CMS 作るぞ! • アイコンを登録・管理するための社内サービス • プランナー・デザイナー自身がアイコンを追加する • 追加されるアイコンのレビュー・承認作業を行うフォーラム • サービス毎にアイコンフォントのサブセットを管理できるとなお良さそう

Slide 11

Slide 11 text

• データ取得/操作をクライアントサイドで制御する言語・実行環境 • GraqhQLサーバーにクエリを投げると、そのとおりのデータが返る GraphQLについて query { user(id: "123") { id name } } { "data": { "user": { "id": “123", "name": “spring-raining" } } }

Slide 12

Slide 12 text

なぜGraphQLを使うのか • フロントエンド側にとって、REST APIにはないメリットがいっぱい • APIリクエスト数の削減 • 余分なレスポンスの削減 • 社内サービスではすでに採用事例もたくさん • 普段業務でサーバサイドを触ることが無いので興味本位で

Slide 13

Slide 13 text

GraphQL Serverをつくる

Slide 14

Slide 14 text

• 別途APIサーバーなどのBackendを持つBFFの構造ではなく、DB接 続、Session管理、GraphQLエンドポイントが一体のシンプルな構成 LAICON Backend CLI CMS web page Backend GraphQL API 社内認証基盤 Session (Redis) DB (MySQL)

Slide 15

Slide 15 text

DBと接続 • TypeORMを使い、DB (MySQL) と TypeScriptのclassとマッピング • DecoratorでColumn等を定義 • DB関連はTypeORMに全ておまかせ @Entity('users') class User { @PrimaryColumn() id: string; @Column({ nullable: true }) name?: string; @OneToMany( type => Icon, icon => icon.user ) icons: Icon[]; } @Entity('icons') class Icon { @PrimaryColumn() id!: string; @ManyToOne( type => User, user => user.icons ) user: User; }

Slide 16

Slide 16 text

GraphQL SDLとTypeScriptの同期 • GraphQL SDL(APIで取得できるデータ構造の定義言語)と TypeScriptは互換性があり、(だいたい)相互変換できる GraphQL SDL TypeScript graphql-codegen type-graphql

Slide 17

Slide 17 text

@Entity('users') class User { @PrimaryColumn() @Field() id: string; @Column({nullable: true}) @Field( type => String, {nullable: true} ) name?: string; @OneToMany( type => Icon, icon => icon.user ) @Field(type => [Icon]) icons: Icon[]; } Entityの定義 @Resolver(User) class UserResolver { @Query(() => User, {nullable: true}) async user( @Arg('id') id: string ): Promise { // implement } @Mutation(() => User) async updateName( @Arg('id') id: string, @Arg('name') name: string ): Promise { // implement } } Query/Mutationの定義 type Query { user(id: String!): User } type Mutation { updateName( id: String! string: String! ): User! } type User { id: String! name: String icons: [Icon!]! } できあがるSDL

Slide 18

Slide 18 text

フォーラム機能の実現は少し大変 ユーザーがアイコンを アップロードして申請 デザイナー・エンジニアが レビュー リテイク要求 LAICON アイコンを追加されると 自動でアイコンフォントを リリース

Slide 19

Slide 19 text

フォーラム機能の実現は少し大変 ユーザーがアイコンを アップロードして申請 デザイナー・エンジニアが レビュー リテイク要求 LAICON アイコンを追加されると 自動でアイコンフォントを リリース このワークフロー どこかに見覚えはありませんか…?

Slide 20

Slide 20 text

Pull Request

Slide 21

Slide 21 text

GitHubのPull Requestと同じ! • 都合の良いことにGitHub API v4はGraphQLで提供されている • 社内のGitHub Enterprise APIをそのまま使ってしまえばいいので は?? • GitHub上にあるコメント等の情報がそのまま利用できる

Slide 22

Slide 22 text

GraphQL Serverをつなぐ

Slide 23

Slide 23 text

Apollo Federation • Apollo Serverが用意する機能 • 複数のGraphQL APIをまとめあげ、APIの連合を作る • それぞれのSchemeのtypeを関連付けることができる

Slide 24

Slide 24 text

複数のGraphQL Schemeの関連付け • LAICONのユーザーとGitHubアカウントを相互に参照したい • GitHub v4 APIにはUserやBotを抽象化したActorという概念がある ので、Actorのアカウント名からユーザーのObject Typeを引けるよう にする API Endpoint GitHub v4 API LAICON API

Slide 25

Slide 25 text

Federated schemaの作成 type User @key(fields: "name") { id: String! name: String @external icons: [Icon!]! } extend type Actor { user: User @provides(fields: "name") } GitHub側のActor objectに @provides directiveを与える const schema = buildFederatedSchema({ typeDefs, resolvers: { ...resolvers, Actor: { user(parent, args, context, info) { return findUsersByGithubName(parent.login); }, }, }, }); Resolversに実際の取得処理を書く LAICON側のSDL

Slide 26

Slide 26 text

Apollo Gateway • 用意したApollo serverの立ち上がっ ているURLを指定 • Apollo Federationに対応していれ ば、勝手にQueryやMutationをマージ してくれる const gateway = new ApolloGateway({ serviceList: [ { name: 'laicon', url: 'http://localhost:5001', }, { name: 'github', url: 'http://localhost:5002', }, ], });

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

まとめ • GitHub v4 APIの利用はいろいろ考えるべき点はあるが、すでにある GraphQL APIを拡張して利用するアイディアは便利 • 世の全てのAPIがGraphQLで提供されてほしい…