この記事は Angular Advent Calendar 2018 の 22 日目の記事です。
概要
- AWS AppSyncを使って画面にデータを表示してみたい方
- フロントエンドエンジニアでも簡単にGraphQLを触ってみたい方
- GraphQLを導入するか迷っている方向けの記事
RESTがつらい
上の図のようにAngular + AWSを使い
REST APIから返ってきた情報を表示するサービスを運用しています。
ただ、サービスの要件が増えるにつれて画面で取得したい情報など多くなるもので
- 複数のAPIを呼び出さないと欲しい情報が取れない
- レスポンス内の一部のデータしか利用しないのに、余分なデータも返される
- APIのリクエスト数やRTTの増加
など色々つらい部分が多くなってきました…。
なぜGraphQL?
じゃあこの問題をどう解決するか?
- 欲しい情報だけ返す新しいAPIを増やす
- 既存のAPIにfieldsパラメータなどを実装する
など方法は色々あると思うのですが
GraphQLの場合、スキーマ設定次第で
- 複数のサービスからシンプルに無駄なく欲しい情報を取得できる
- リポジトリに対してクエリを生やすことでデータの取得が可能になるため、既存のプロジェクトに影響を与えず小さく導入できそう
という点で魅力的に思えたので、
今回、GraphQLのサービスである AWS AppSync を使い
Angular + Apolloを利用してデータを実装してみたので、その情報を共有していきたいと思います。
AWS + Angularで簡単にGraphQLをはじめるには?
おおまかな流れ
- こちらを参考にしながらAWS AppSyncを作成 (構築の手順は省略させていただきます。)
- Apollo + AWS AppSync JavaScript SDK のインストール
- Angularで実装
完成コード
今回の完成コードはこちらに置いてあります。
https://github.com/hiroyuki-nishi/apollo-angular
今回利用するサービスの説明
AWS AppSyncは、AWSが提供しているフルマネージドなサーバーレスなGraphQLサービスです。
他のAWS リソースとの連携が容易であったり、DynamoDB をデータソースとすると、GraphQLのスキーマが自動生成や、AppSyncのコンソール上で結果を確認することができます。
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に以下を追加します。
// polyfills.ts
(window as any).global = window;
Angularからデータを取得
次に、AWS AppSyncからデータを取得するサービスを作成します。
ここでは主に、AWS AppSyncのエンドポイントの設定を行なっています。
//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のドキュメントを参照しながら
今回は、複数のリポジトリから情報を取得することを想定したクエリを実装しました。
//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
}
}
}
`;
}
最後に表示するコンポーネントを作成します。
// 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リクエストで複数のリポジトリから、欲しい情報だけ取得できました。すごい。
まとめ
実際にAWS AppSyncを実運用するにあたって
AWSの制限や実際に使ってみないとわからないことがあると思いますが
一つのクエリで複数のデータソースを組み合わせ欲しい情報に到達することができるのは
魅力的で、それを AWS リソースに対し手軽に行えるのはやはりよかったです。
今年も残りわずかですが
今からでもGraphQLを始めてみてはいかがでしょうか!
23日目は @studioTeaTwo さんです。よろしくお願いします。