50
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AngularAdvent Calendar 2018

Day 22

AWS AppSync + ApolloではじめるGraphQL

Posted at

この記事は Angular Advent Calendar 2018 の 22 日目の記事です。

概要

  • AWS AppSyncを使って画面にデータを表示してみたい方
  • フロントエンドエンジニアでも簡単にGraphQLを触ってみたい方
  • GraphQLを導入するか迷っている方向けの記事

RESTがつらい

(例)AWS構成図
aws.png

上の図のようにAngular + AWSを使い
REST APIから返ってきた情報を表示するサービスを運用しています。
ただ、サービスの要件が増えるにつれて画面で取得したい情報など多くなるもので

  • 複数のAPIを呼び出さないと欲しい情報が取れない
  • レスポンス内の一部のデータしか利用しないのに、余分なデータも返される
  • APIのリクエスト数やRTTの増加

など色々つらい部分が多くなってきました…。

なぜGraphQL?

じゃあこの問題をどう解決するか?

  • 欲しい情報だけ返す新しいAPIを増やす
  • 既存のAPIにfieldsパラメータなどを実装する

など方法は色々あると思うのですが

GraphQLの場合、スキーマ設定次第で

  • 複数のサービスからシンプルに無駄なく欲しい情報を取得できる
  • リポジトリに対してクエリを生やすことでデータの取得が可能になるため、既存のプロジェクトに影響を与えず小さく導入できそう

という点で魅力的に思えたので、
今回、GraphQLのサービスである AWS AppSync を使い
Angular + Apolloを利用してデータを実装してみたので、その情報を共有していきたいと思います。

AWS + Angularで簡単にGraphQLをはじめるには?

おおまかな流れ

  1. こちらを参考にしながらAWS AppSyncを作成 (構築の手順は省略させていただきます。)
  2. Apollo + AWS AppSync JavaScript SDK のインストール
  3. Angularで実装

AWS構成図のイメージはこんな感じです。
appsync.png

完成コード

今回の完成コードはこちらに置いてあります。
https://github.com/hiroyuki-nishi/apollo-angular

今回利用するサービスの説明

AWS AppSync(バックエンド)
appsync (1).png

AWS AppSyncは、AWSが提供しているフルマネージドなサーバーレスなGraphQLサービスです。
他のAWS リソースとの連携が容易であったり、DynamoDB をデータソースとすると、GraphQLのスキーマが自動生成や、AppSyncのコンソール上で結果を確認することができます。

Apollo(フロントエンド)
apollo-logo.png

Apolloは、Meteor Development Groupが開発している
バックエンド && フロントエンドでGraphQLが使えるライブラリです。

Angular、React、Vue、Meteor、Ember、Polymerなどのフレームワークなどに対応しており
今回はApolloを使ってGraphQLのクライアントサイドを実装してみたいと思います。

まずはインストール!

AWS AppSyncが無事作成できましたら、Angularの実装を行なっていきます。
まずは、新しいプロジェクトを作成しApolloとAWS AppSyncSDKを追加します。

$ ng new apollo-in-angular
$ ng add apollo-angular
$ npm install --save aws-appsync

Angular 6.x以降でAWS AppSyncSDKを動作させるために、polyfills.tsに以下を追加します。

.ts
// polyfills.ts
(window as any).global = window;

Angularからデータを取得

次に、AWS AppSyncからデータを取得するサービスを作成します。
ここでは主に、AWS AppSyncのエンドポイントの設定を行なっています。

.ts
//graphql.service.ts
import AWSAppSyncClient from 'aws-appsync';
import { AUTH_TYPE } from 'aws-appsync/lib';
import { Apollo } from 'apollo-angular';
import { Injectable } from '@angular/core';


@Injectable()
export class GraphqlService {
  constructor(private apollo: Apollo) {}

  hydrated() {
    const appsyncClient = new AWSAppSyncClient({
      disableOffline: true,
      url: '<Your AppSync Api Url>',
      region: '<Your AppSync Api Region>',
      auth: {
        type: AUTH_TYPE.API_KEY,
        apiKey: '<Your AppSync ApiKey>',
      },
    });
    this.apollo.setClient(appsyncClient);
    return appsyncClient.hydrated();
  }
}

次にQueryサービスを定義します。
Apolloのドキュメントを参照しながら
今回は、複数のリポジトリから情報を取得することを想定したクエリを実装しました。

.ts
//query.service.ts
import {Injectable} from '@angular/core';
import {Query} from 'apollo-angular';
import gql from 'graphql-tag';

export interface Application {
  id: string;
  itunesstore_id: string;
  updated: string;
}

export interface Profile {
  identifier: string;
}

export interface ApplicationsWithProfiles {
  listApplications: {
    items: Application[];
  };
  listProfiles: {
    items: Profile[];
  };
}


@Injectable({
  providedIn: 'root',
})
export class ApplicationsGQL extends Query<ApplicationsWithProfiles> {
  document = gql`
    query {
      listApplications {
        items {
          id
          itunesstore_id
          updated
        }
      }
    listProfiles {
        items {
          identifier
        }
      }
    }
  `;
}

最後に表示するコンポーネントを作成します。

.ts
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { map } from 'rxjs/operators';
import { Application, QueryGQL, Profile } from './query.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  title = 'GraphQL with Apollo';
  applications: Application[];
  profiles: Profile[];

  constructor(private service: QueryGQL) {}

  ngOnInit(): void {
    this.service.watch().valueChanges.pipe(
      map(v => v.data)
    ).subscribe(res => {
      this.applications = res.listApplications.items;
      this.profiles = res.listProfiles.items;
    });
  }
}

こちらが完成した画面になります。
無事1リクエストで複数のリポジトリから、欲しい情報だけ取得できました。すごい。

スクリーンショット 2018-12-21 23.07.51.png

まとめ

実際にAWS AppSyncを実運用するにあたって
AWSの制限や実際に使ってみないとわからないことがあると思いますが
一つのクエリで複数のデータソースを組み合わせ欲しい情報に到達することができるのは
魅力的で、それを AWS リソースに対し手軽に行えるのはやはりよかったです。

今年も残りわずかですが
今からでもGraphQLを始めてみてはいかがでしょうか!

23日目は @studioTeaTwo さんです。よろしくお願いします。

50
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?