North Detail / ノースディテール

BLOG ブログ

ブログ
CATEGORY
TECH

AWS Amplify の @function ディレクティブを使った「おみくじ」サイトの作成

こんにちは、 tacck です。

以前に書いた Amplify で開発してみる シリーズにて、 API (GraphQL) での開発の流れをみていきました。
この時は、主に AppSync + DynamoDB によるデータ操作、 Cognito による認証、に関するところを中心に説明していきました。

今回は、 API (GraphQL) で使える機能として、 @function ディレクティブを使った Lambda 連携の例を説明していきたいと思います。

題材として簡単な「おみくじ」のようなサイトを作ってみましょう。イメージは下記のような動画の動作となります。

ソースコード全体はこちら:

GitHub tacck/sample-amplify-fortune

開発

Amplify CLI を使うので、前準備は公式ドキュメントを参照してください。

Tutorial - Prerequisites - Amplify Docs

同様に、 Vue CLI も使用します。こちらも公式ドキュメントを参照してください。

Installation | Vue CLI

Vue プロジェクト作成

まずは、 Vue CLI でプロジェクトを作成します。

$ vue create sample-amplify-fortune


Vue CLI v4.5.11
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, Linter
? Choose a version of Vue.js that you want to start the project with 2.x
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No

(snip)

$ cd sample-amplify-fortune 
$ vue add vuetify
/[YOUR_HOME_DIRECTORY]/.anyenv/envs/nodenv/plugins/nodenv-vars/bin/nodenv-vars: line 73: /dev/fd/62: Interrupted system call

📦  Installing vue-cli-plugin-vuetify...

(snip)

? Choose a preset: Default (recommended)

(snip)

$

色の薄くなっている行が入力箇所となります。こちらを参考に、入力してみてください。

Amplify プロジェクト設定

このプロジェクトを Amplify のプロジェクトとして設定します。

$ amplify init
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project sampleamplifyfortune
? Enter a name for the environment dev
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using vue
? Source Directory Path:  src
? Distribution Directory Path: dist
? Build Command:  yarn build
? Start Command: yarn serve
Using default provider  awscloudformation

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

? Do you want to use an AWS profile? Yes
? Please choose the profile you want to use default
Adding backend environment dev to AWS Amplify Console app: XXXXXXXXXXXXXX
⠇ Initializing project in the cloud...

(snip)

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

$

引き続き、 UI Components の追加を行ないます。

$ yarn add aws-amplify @aws-amplify/ui-vue

そして、 src/main.js ファイルを下記のように修正します。

import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import '@aws-amplify/ui-vue'
import Amplify from 'aws-amplify'
import awsconfig from './aws-exports'

Amplify.configure(awsconfig)
Vue.config.productionTip = false

new Vue({
  vuetify,
  render: h => h(App),
}).$mount('#app')

ここまでで、 Amplify を使い始める準備は完了です。

おみくじ機能の実装

今回は API (GraphQL) から Lambda を呼び出しておみくじの結果を取得する、という実装となります。

まずは API (GraphQL) 機能を有効にします。

$ amplify add api
? Please select from one of the below mentioned services: GraphQL
? Provide API name: sampleamplifyfortune
? Choose the default authorization type for the API API key
? Enter a description for the API key: 
? After how many days from now the API key should expire (1-365): 365
? Do you want to configure advanced settings for the GraphQL API No, I am done.
? Do you have an annotated GraphQL schema? No
? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)

The following types do not have '@auth' enabled. Consider using @auth with @model
         - Todo
Learn more about @auth here: https://docs.amplify.aws/cli/graphql-transformer/auth


GraphQL schema compiled successfully.

Edit your schema at /[YOUR_DIRECTORY]/sample-amplify-fortune/amplify/backend/api/sampleamplifyfortune/schema.graphql or place .graphql files in a directory at /[YOUR_DIRECTORY]/sample-amplify-fortune/amplify/backend/api/sampleamplifyfortune/schema
? Do you want to edit the schema now? No
Successfully added resource sampleamplifyfortune 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

$

ここは、とりあえず API 機能を使えるように API_KEY による有効化を行ないます。

続けて、 Lambda を準備するために Function 機能を有効にします。

$ amplify add function
? Select which capability you want to add: Lambda function (serverless function)
? Provide an AWS Lambda function name: sampleamplifyfortuneXXXXXXXX
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: Hello World

Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation
- Lambda layers configuration

? Do you want to configure advanced settings? No
? Do you want to edit the local lambda function now? Yes
Please edit the file in your editor: /[YOUR_DIRECTORY]/sample-amplify-fortune/amplify/backend/function/sampleamplifyfortuneXXXXXXXX/src/index.js
? Press enter to continue 
Successfully added resource sampleamplifyfortuneXXXXXXXX locally.

Next steps:
Check out sample function code generated in <project-dir>/amplify/backend/function/sampleamplifyfortuneXXXXXXXX/src
"amplify function build" builds all of your functions currently in the project
"amplify mock function <functionName>" runs your function locally
"amplify push" builds all of your local backend resources and provisions them in the cloud
"amplify publish" builds all of your local backend and front-end resources (if you added hosting category) and provisions them in the cloud

$

これで、必要な機能を有効化することができました。

続けて実装していきましょう。

Lambda の方では、呼ばれたらランダムに結果を返すような実装を行ないます。

const results = ['Lucky! 😆', 'So so 😐', 'Bad 🥺']

exports.handler = async event => {
  return results[Math.floor(Math.random() * results.length)]
}

次に、 GraphQL の Schema から Lambda を呼び出すように、 @function ディレクティブを設定します。

type Query {
  drawFortune: String @function(name: "sampleamplifyfortuneXXXXXXXX-${env}")
}

こちらの詳しい情報を知りたい方は、公式のドキュメントを参照してみてください。

API (GraphQL) - How to use Lambda GraphQL Resolvers - Amplify Docs

ここまで実装できたら、 Amplify を push しましょう。

$ amplify push
✔ Successfully pulled backend environment dev from the cloud.

Current Environment: dev

| Category | Resource name                | Operation | Provider plugin   |
| -------- | ---------------------------- | --------- | ----------------- |
| Api      | sampleamplifyfortune         | Create    | awscloudformation |
| Function | sampleamplifyfortuneXXXXXXXX | Create    | awscloudformation |
? Are you sure you want to continue? Yes

GraphQL schema compiled successfully.

Edit your schema at /[YOUR_DIRECTORY]/sample-amplify-fortune/amplify/backend/api/sampleamplifyfortune/schema.graphql or place .graphql files in a directory at /[YOUR_DIRECTORY]/sample-amplify-fortune/amplify/backend/api/sampleamplifyfortune/schema
? Do you want to generate code for your newly created GraphQL API Yes
? Choose the code generation language target javascript
? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js
? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes
? Enter maximum statement depth [increase from default if your schema is deeply nested] 2
⠴ Updating resources in the cloud. This may take a few minutes...

(snip)

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


$

これでバックエンド側が準備できたので、続けてフロントエンドの実装です。

Lambda を呼び出すのですが、フロントエンド側からは、今まで通りの GraphQL の呼び出し方で対応できます。

下記のような Fortune.vue を新規作成します。

<template>
  <v-container>
    <v-row justify="center">
      <v-col cols="6"
        ><v-btn block color="primary" @click="drawFortune"
          >Draw Fortune</v-btn
        ></v-col
      >
    </v-row>
    <v-row justify="center">
      <v-col cols="6">
        <v-card class="pa-4">
          <v-card-title class="text-h2 justify-center">{{
            fortune
          }}</v-card-title>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import { API, graphqlOperation } from 'aws-amplify'
import { drawFortune } from '../graphql/queries'

export default {
  data: function() {
    return {
      fortune: '',
    }
  },
  methods: {
    async drawFortune() {
      const result = await API.graphql(graphqlOperation(drawFortune))
      this.fortune = result.data.drawFortune
    },
  },
}
</script>

<style></style>

App.vue でこのコンポーネントを呼び出すようにすれば、準備完了です。

<template>
...
(snip)
...
    <v-main>
      <Fortune />
    </v-main>
  </v-app>
</template>

<script>
import Fortune from './components/Fortune'

export default {
  name: 'App',
  components: {
    Fortune,
  },
}
</script>

ここまでできたら、実装完了です。

動作確認

それでは、動作確認してみましょう。まずは、下記コマンドを実行します。

$ yarn serve

しばらく待ったら、 http://localhost:8080 へアクセスしましょう。

こちらの動画のように動いたら、無事完成です!

まとめ

フロントエンドのライブラリから AWS Lambda のようなサービスを実行するためには、それぞれのサービスの URL へアクセスを行なう必要がありました。
そのため、使いたい Lambda が増えるたびに、フロントエンドで管理する URL も増えていきます。

今回のような AWS Amplify から GraphQL (AWS AppSync) を経由することで、 URL 管理の手間を省いた形でサービスを呼び出すような実装ができるようになります。
(必要なコードも自動生成してくれるので、開発者が実装する内容は最小限になります。)

こういったところも、 AWS Amplify を使う利点となります。

ぜひ、皆さんも AWS Amplify を使ってみてください。

tacck
WRITER:tacck
元 技術推進Group Group Leader

現在は株式会社ノースディテールを離れて、
エバンジェリストとして技術啓蒙や勉強会の開催、各種プロジェクトに参画しています。
機会があれば、ノースディテールでのプロジェクトに参加できればと思っています。

言語は問わずに対応しますが、心はPHPer。
フロントエンド・バックエンド・インフラ・スマホアプリなどを、
「垣根を超えて」どう作るか、を考えるのが好きです。

好きなフィギュアスケートの技はスプレッド・イーグル。
主な記事 一覧へ

一覧へ

IS 501383 / ISO 27001