Angularアドベントカレンダー 2021 18日目の記事です。1時間ほど遅刻しましたすみません…。
AWS AmplifyのAngularチュートリアル https://docs.amplify.aws/start/q/integration/angular/ をAngular初級者が試した記録について書きます。

AWS Amplifyとは?

公式ページのトップには「フロントエンドのウェブ/モバイルデベロッパーが AWS でフルスタックアプリケーションをすばやく簡単に構築できるようにする専用のツールと一連の機能」と書かれています。 読んでも何ができるかわからないのでAngular向けチュートリアルをやりながら理解してみようと思います。

手順

Amplify cliのインストール

$ npm install -g @aws-amplify/cli

amplify configure

$ amplify configure
Sign in to your AWS administrator account:
https://console.aws.amazon.com/
Press Enter to continue

Specify the AWS Region
? region:  ap-northeast-1
Specify the username of the new IAM user:
? user name:  amplify-****
Complete the user creation using the AWS console
https://console.aws.amazon.com/iam/home?***
Press Enter to continue

Enter the access key of the newly created user:
? accessKeyId:  ********************
? secretAccessKey:  ****************************************
This would update/create the AWS Profile in your local machine
? Profile Name:  my

Successfully set up the new user.

コマンド打ったらブラウザで勝手にAWS管理画面が開いてビビりましたw
管理画面で指示通りにIAMユーザーを作成し、アクセスキーとシークレットキーを入力して設定完了です。

Angularプロジェクト内でamplify init

$ AWS_PROFILE=my amplify init
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project tryoutamplify
The following configuration will be applied:

Project information
| Name: tryoutamplify
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: angular
| Source Directory Path: src
| Distribution Directory Path: dist/tryout-amplify
| Build Command: npm run-script build
| Start Command: ng serve

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: AWS profile

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

? Please choose the profile you want to use my
Adding backend environment dev to AWS Amplify app: ****
⠋ Initializing project in the cloud...

CREATE_IN_PROGRESS **** AWS::CloudFormation::Stack Sat Dec 17 2021 23:49:32 GMT+0900 (日本標準時) User Initiated             
CREATE_IN_PROGRESS AuthRole                         AWS::IAM::Role             Sat Dec 18 2021 23:49:36 GMT+0900 (日本標準時)                            
CREATE_IN_PROGRESS DeploymentBucket                 AWS::S3::Bucket            Sat Dec 18 2021 23:49:36 GMT+0900 (日本標準時)                            
CREATE_IN_PROGRESS UnauthRole                       AWS::IAM::Role             Sat Dec 18 2021 23:49:36 GMT+0900 (日本標準時)                            
CREATE_IN_PROGRESS UnauthRole                       AWS::IAM::Role             Sat Dec 18 2021 23:49:37 GMT+0900 (日本標準時) Resource creation Initiated
CREATE_IN_PROGRESS AuthRole                         AWS::IAM::Role             Sat Dec 18 2021 23:49:37 GMT+0900 (日本標準時) Resource creation Initiated
⠹ Initializing project in the cloud...

CREATE_IN_PROGRESS DeploymentBucket AWS::S3::Bucket Sat Dec 18 2021 23:49:38 GMT+0900 (日本標準時) Resource creation Initiated
⠧ Initializing project in the cloud...

CREATE_COMPLETE UnauthRole AWS::IAM::Role Sat Dec 18 2021 23:49:56 GMT+0900 (日本標準時) 
CREATE_COMPLETE AuthRole   AWS::IAM::Role Sat Dec 18 2021 23:49:56 GMT+0900 (日本標準時) 
⠏ Initializing project in the cloud...

CREATE_COMPLETE DeploymentBucket AWS::S3::Bucket Sat Dec 18 2021 23:49:59 GMT+0900 (日本標準時) 
⠙ Initializing project in the cloud...

CREATE_COMPLETE *** AWS::CloudFormation::Stack Sat Dec 18 2021 23:50:03 GMT+0900 (日本標準時) 
✔ Successfully created initial AWS cloud resources for deployments.
✔ Initialized provider successfully.
Initialized your environment successfully.

Your project has been successfully initialized and connected to the cloud!

Some next steps:
"amplify status" will show you what you've added already and if it's locally configured or deployed
"amplify add <category>" will allow you to add features like user login or a backend API
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify console" to open the Amplify Console and view your project status
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

Pro tip:
Try "amplify add api" to create a backend API and then "amplify publish" to deploy everything

なんだかよくわかりませんが、いきなりデプロイされたぽいです :sweat_smile:

Angular用のAmplifyライブラリを追加

$ npm install aws-amplify @aws-amplify/ui-angular

チュートリアルの指示通りにapp.module.tsにAmplifyUIAngularModuleをimportしましたが、aws-amplify/ui-angularからそんなモジュールはexportされてないというエラーが出てしまいました :sweat_drops: ソースを読みに行ってみるとたしかにそんなモジュールは存在してなかったのでモジュール組み込みはrevertします。

APIを追加する

$ amplify add api
? Select from one of the below mentioned services: GraphQL # REST or GraphQLからGraphQLを選択
? Here is the GraphQL API that we will create. Select a setting to edit or conti
nue Continue
? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description) # Single object, One-to-many relationship, Blankから選択
GraphQL schema compiled successfully.

Edit your schema at /path/to/project/amplify/backend/api/tryoutamplify/schema.graphql or place .graphql files in a directory at /path/to/project/amplify/backend/api/tryoutamplify/schema
✔ Do you want to edit the schema now? (Y/n) · yes
? Choose your default editor: Vim (via Terminal, Mac OS only)  

チュートリアル通りの選択肢を選んで、エディタはVimを選びました。
するとターミナル上でvimが開いてデフォルトで Todo のスキーマが出てきました。チュートリアル通りのレストラン情報に内容をvim上で変更します。

input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY!

type Restraurant  @model {
  id: ID!
  name: String!
  description: String!
  city: String!
}

vimで書き込んで閉じると完了です。

✅ Successfully added resource tryoutamplify locally

✅ Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

amplify/backend/api/tryoutamplify/schema.graphql にスキーマのファイルができていました。
image

$ AWS_PROFILE=my amplify push
⠏ Fetching updates to backend environment: dev from the cloud.⠋ Building resourc⠋ Building resource api/tryoutamplify
⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

⠋ Fetching updates to backend environment: dev from the cloud.GraphQL schema compiled successfully.

Edit your schema at /path/to/project/amplify/backend/api/tryoutamplify/schema.graphql or place .graphql files in a directory at /path/to/project/amplify/backend/api/tryoutamplify/schema
✔ Successfully pulled backend environment dev from the cloud.
⠧ Building resource api/tryoutamplify
⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

GraphQL schema compiled successfully.

Edit your schema at /path/to/project/amplify/backend/api/tryoutamplify/schema.graphql or place .graphql files in a directory at /path/to/project/amplify/backend/api/tryoutamplify/schema

    Current Environment: dev
    
┌──────────┬───────────────┬───────────┬───────────────────┐
│ Category │ Resource name │ Operation │ Provider plugin   │
├──────────┼───────────────┼───────────┼───────────────────┤
│ Api      │ tryoutamplify │ Create    │ awscloudformation │
└──────────┴───────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? Yes

⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

GraphQL schema compiled successfully.

Edit your schema at /path/to/project/amplify/backend/api/tryoutamplify/schema.graphql or place .graphql files in a directory at /path/to/project/amplify/backend/api/tryoutamplify/schema
⠧ Building resource api/tryoutamplify
⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

GraphQL schema compiled successfully.

Edit your schema at /path/to/project/amplify/backend/api/tryoutamplify/schema.graphql or place .graphql files in a directory at /path/to/project/amplify/backend/api/tryoutamplify/schema
? Do you want to generate code for your newly created GraphQL API Yes
? Choose the code generation language target angular
? Enter the file name pattern of graphql queries, mutations and subscriptions sr
c/graphql/**/*.graphql
? Do you want to generate/update all possible GraphQL operations - queries, muta
tions and subscriptions Yes
? Enter maximum statement depth [increase from default if your schema is deeply 
nested] 2
? Enter the file name for the generated code src/app/API.service.ts
Updating resources in the cloud. This may take a few minutes...
# (中略)
✔ All resources are updated in the cloud

GraphQL endpoint: https://***.appsync-api.ap-northeast-1.amazonaws.com/graphql
GraphQL API KEY: ***

なんとこれだけでGraphQLなAPIができたらしいです! :smile: 「マジで?!」とGraphQL endpointにいきなりブラウザアクセスしてエラー出しちゃいました :sweat_smile:

{
  "errors" : [ {
    "message" : "Invalid URI format",
    "errorType" : "MalformedHttpRequestException"
  } ]
}

src/app/API.service.ts にAPIリクエスト用のサービスもできていました。 API.service.ts

GraphQLのAPIコンソールを使う

$ AWS_PROFILE=my amplify console api

またいきなりブラウザにタブが増えてビビりました(二度目)
ここでは画面上でGraphQLを試すことができました。データを取得したり(query)、データを更新したり(mutate)できます。

GraphQL console

フロントエンドからAPIを使う

せっかくなのでGraphQLをフロントエンドから呼んでみたいと思います。

// src/main.ts
+ import Amplify from 'aws-amplify';
+ import aws_exports from './aws-exports';
+ Amplify.configure(aws_exports);

チュートリアルからコピペするとエラーが出たので、strict mode対策についてのチュートリアル内からのリンク先 https://docs.amplify.aws/lib/troubleshooting/strict-mode/q/platform/js/#declaration-file-for-aws-exports のアドバイスに従って、 src/aws-exports.d.ts も作成しました。

// src/aws-exports.d.ts
declare const awsmobile: Record<string, any>
export default awsmobile;

これでAPIを呼ぶ準備ができたはずなので、src/app.component.tsにAPIコールのコードを追加してみます。(GraphQLのスキーマを作るときに レストラン をtypoしてるのでチュートリアルからコピペしてtypoを反映しました…)
チュートリアルではレストランデータの作成のサンプルコードが載ってるんですが、今回は時間の関係で単純にAPIから取得したデータを表示するだけにしています。

// src/app.component.ts
import { Component } from '@angular/core';
import { APIService, Restraurant } from './API.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'tryout-amplify';
  data: Restraurant | undefined;

  constructor(private api: APIService) {
  }

  public show(): void {
    this.api.GetRestraurant('1').then((response) => {
      this.data = response;
    });
  }
}
// src/app.component.html
<button type="button" (click)="show()">今週のおすすめレストランを見る</button>
<div *ngIf="data">
    <h1>今週のおすすめレストラン</h1>
    <ul>
        <li>{{data.name}}</li>
        <li>{{data.city}}</li>
        <li>{{data.description}}</li>
    </ul>
</div>

ng serve して見てみると…!!
さっきamplify console apiで作成したデータをAPIから呼び出して表示することができました!!

716ab32d90aa0f6e628778154b899706

ブラウザの開発者ツールで見てみるとAPIコール時には x-api-key ヘッダでちゃんとAPIキーが送られていました。
API keyは amplify/backend/amplify-meta.json にどこかのタイミング(amplify pushしたときかな?)で書き込まれていたので、それを参照しているんだと思われます。(Angularのenvironmentには何もdiffありませんでした)

まとめ

かなり簡単にAPIと連携するAngularアプリケーションを作れそうだなということはわかりました。
単にCRUDするAPIを作り、そこにデータを送るAngularアプリだけならAmplifyでもいいのかもしれません(実際はCRUD以上のことをやるAPIを作っているので私はPHPとSymfonyが手放せないわけですが… :sweat_smile: )。

「APIが必要=バックエンドエンジニアが必要」ではないことが実感でき危機感も生まれました。
認証やファイル保存, Pub/Sub等のNext Stepsにある項目もいずれ試してみたいと思います。 https://docs.amplify.aws/start/getting-started/nextsteps/q/integration/angular/

遊び終わったAmplifyリソースは

$ amplify delete

で消すことができました :smile:

余談

最後に、フロントエンド苦手なPHPerの私がなぜAngularを選んだかという話をさせてください。
私はカルテットに入社して最初の数年はSymfonyだけでなく先輩エンジニアに習いながらAngularJSも書いていましたが、徐々に分業と職種別チーム分けが進んだ結果、ここ数年はほぼSymfonyとPHPしか書いていませんでした。
しかし、今年6月から新しい開発プロジェクトをスクラムで進めることになり、画面よりも内部実装の複雑さに向けてスクラムチームをPHPチームメインで編成したため、フロントエンドの知識がほぼないメンバーのみで開発を担当することになってしまいました。
当初、画面についてはPHPerなら誰でも(?)多少は嗜んでいるはずのjQueryでなんとかしようと思ったのですが、ユーザー入力によってかなり細かく変化するフォームを作らねばならず、jQueryは諦めざるを得ませんでした。
そこで3大勢力(?)のVue, React, Angularから「どれを選ぶか?」となったとき、社内に有識者がいていつでも質問できることからAngularを選択しました。モブプロしたり、UIチームに質問しまくったりしながら開発を進めてきて、とうとう今月実際に想定ユーザーに使ってもらえるところまできました :tada:
いまではバックエンドメインだったプログラマーにとってはAngularは割ととっつきやすいのかなと思っています。
PHPもSymfonyのコミュニティに色々教えてもらってここまできた私なので、Angularもng-japan on-airを毎月聞いて、コミュニティに育ててもらう気満々です :smile: これからどうぞよろしくお願いします!!!