VueにAmplifyを入れてみた
この記事はVue.js #3 Advent Calendar 2018の4日目の記事です。
フロントエンドのライブラリかつAWSのリソースを作ることができるツールとして話題のAmplifyをVuejsに組み込んでみたいと思います。
- Amplifyとは
- CLIのインストール
- Vueプロジェクトの初期化
- Amplifyの初期化
- Cognitoの作成
- AppSyncの作成
- Vueパッケージをインストール
- ユーザーの認証画面を作成する
- GraphQLにリクエストしてみる
- まとめ
Amplifyとは
AmplifyはAWSリソースとの接続を支援するオープンソースのJavaScriptライブラリです。
強力なCLIツールが提供されていて、AWSリソースの作成をコマンド上で実行し、ライブラリに反映することができます。
現在はCognitoによる認証や、AppSyncを用いたGraphQLの利用がサポートされています。
The foundation for your cloud-powered mobile & web apps
CLIのインストール
インストールはNPMで行います。
$ npm i -g @aws-amplify/cli
下記コマンドで詳細が出力されたらインストール成功です。
$ amplify
Vueプロジェクトの初期化
Amplifyの初期化はプロジェクトのルートディレクトで実行することを推奨されているため、先にVueのプロジェクトを作成します。 実行はVue CLIを用いています。
keinuma% vue create amplify-vue-demo Vue CLI v3.1.3 ? Please pick a preset: Manually select features ? Check the features needed for your project: Babel, Router, Vuex, Linter ? Use class-style component syntax? Yes ? Use Babel alongside TypeScript for auto-detected polyfills? Yes ? Use history mode for router? (Requires proper server setup for index fallback in production) Yes ? Pick a linter / formatter config: ESLint ? Pick additional lint features: Lint on save ? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In package.json ? Save this as a preset for future projects? No
Amplifyの初期化
Amplify CLIを用いてAWS環境の初期化を行います。
$ amplify init
実行すると開発環境およびプロジェクトの情報を渡してあげます。
? 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
Amplifyは現状CloudFormationから各リソースを作成するため、認証情報を教えないといけません。
AWS上でユーザーを作成するか聞かれるので、専用のユーザーを用意する場合はYesを選択しましょう。
リージョンとアカウント名を入力するとIAM作成画面に遷移し、ポリシーの設定を行います。
Using default provider awscloudformation AWS access credentials can not be detected. ? Setup new user Yes Follow these steps to set up access to your AWS account: 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-demo Complete the user creation using the AWS console https://console.aws.amazon.com/iam/home?****
ユーザーを作成したら、コンソールに戻ってクレデンシャル情報を入力します。
Access Key IDおよびSecret Access Keyを入力したら、Amplify上で管理するための名前をつけることができます。
Press Enter to continue Enter the access key of the newly created user: ? accessKeyId: A**************** ? secretAccessKey: ******************************* This would update/create the AWS Profile in your local machine ? Profile Name: demo Successfully set up the new user.
認証情報の設定が完了すると改めて、ユーザー選択を行うので先ほど作ったdemo
を選択します。
? Do you want to use an AWS profile? Yes ? Please choose the profile you want to use demo ⠇ Initializing project in the cloud... CREATE_IN_PROGRESS amplifyvuedemo-20181126103438 AWS::CloudFormation::Stack Mon Nov 26 2018 10:34:38 GMT+0900 (日本標準時) User Initiated CREATE_IN_PROGRESS UnauthRole AWS::IAM::Role Mon Nov 26 2018 10:34:42 GMT+0900 (日本標準時) CREATE_IN_PROGRESS DeploymentBucket AWS::S3::Bucket Mon Nov 26 2018 10:34:42 GMT+0900 (日本標準時) CREATE_IN_PROGRESS AuthRole AWS::IAM::Role Mon Nov 26 2018 10:34:42 GMT+0900 (日本標準時) CREATE_IN_PROGRESS AuthRole AWS::IAM::Role Mon Nov 26 2018 10:34:43 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS UnauthRole AWS::IAM::Role Mon Nov 26 2018 10:34:43 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS DeploymentBucket AWS::S3::Bucket Mon Nov 26 2018 10:34:44 GMT+0900 (日本標準時) Resource creation Initiated ⠹ Initializing project in the cloud... CREATE_COMPLETE UnauthRole AWS::IAM::Role Mon Nov 26 2018 10:35:02 GMT+0900 (日本標準時) CREATE_COMPLETE AuthRole AWS::IAM::Role Mon Nov 26 2018 10:35:02 GMT+0900 (日本標準時) CREATE_COMPLETE DeploymentBucket AWS::S3::Bucket Mon Nov 26 2018 10:35:05 GMT+0900 (日本標準時) ⠸ Initializing project in the cloud... CREATE_COMPLETE amplifyvuedemo::AWS::CloudFormation::Stack Mon Nov 26 2018 10:35:09 GMT+0900 (日本標準時) ✔ Successfully created initial AWS cloud resources for deployments. 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 <category> add" 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 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" t
CloudFormationのStack、デプロイ用のバケットが作成されると初期化は完了になります。
実行完了後に以下のファイルが作成されています。
- .amplifyrc
- amplify/
.amplifyrcはCloudFormationで作成されたリソース情報が記載されていて、amplifyディレクトリ以下にはプロジェクトの情報やリソースの詳細が格納されています。
Cognitoの作成
AmplifyでCognitoユーザープールを作成してみたいと思います。
addコマンドでユーザープールの設定を行います。
認証方法はEmailで、パスワードの強度などをカスタマイズしています。
IdeintityプールはCognitoからAPI以外の他のAWSリソースに紐づけるときに使用します。
例えばS3へのアップロードを許可する場合などですね。
$ amplify add auth Using service: Cognito, provided by: awscloudformation The current configured provider is Amazon Cognito. Do you want to use the default authentication and security configuration? No, I will set up my own configuration. ? Select the authentication/authorization services that you want to use: User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Stor age features for images or other content, Analytics, and more) ? Please provide a friendly name for your resource that will be used to label this category in the project: amplifyauthdemo ? Please enter a name for your identity pool. amplifyvuedemo96530290_identitypool_96530290 ? Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) No ? Do you want to enable 3rd party authentication providers in your identity pool? No ? Please provide a name for your user pool: amplifyvuedemo96530290_userpool_96530290 ? Multifactor authentication (MFA) user login options: OFF ? Email based user registration/forgot password: Enabled (Requires per-user email entry at registration) ? Please specify an email verification subject: パスワード再設定 ? Please specify an email verification message: 認証コードはこちらになります。 {####} ? Do you want to override the default password policy for this User Pool? Yes ? Enter the minimum password length for this User Pool: 8 ? Select the password character requirements for your userpool: Requires Lowercase, Requires Uppercase, Requires Numbers ? Userpool users are created with a standard set of attributes defined by the OpenID Connect specification. Mark the required attributes below: ? Specify the app's refresh token expiration period (in days): 30 ? Do you want to specify the user attributes this app can read and write? Yes ? Specify read attributes: Email ? Specify write attributes: Successfully added resource amplifyauthdemo 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
作成したCognitoをAWSに反映してみる。 init時に作成したCloudFormationにネストしてリソースを作成していることがわかります。
$ amplify push | Category | Resource name | Operation | Provider plugin | | -------- | --------------- | --------- | ----------------- | | Auth | amplifyauthdemo | Create | awscloudformation | ? Are you sure you want to continue? true ⠙ Updating resources in the cloud. This may take a few minutes... UPDATE_IN_PROGRESS amplifyvuedemo-20181126103438 AWS::CloudFormation::Stack Mon Nov 26 2018 11:16:29 GMT+0900 (日本標準時) User Initiated CREATE_IN_PROGRESS authamplifyauthdemo AWS::CloudFormation::Stack Mon Nov 26 2018 11:16:34 GMT+0900 (日本標準時) CREATE_IN_PROGRESS authamplifyauthdemo AWS::CloudFormation::Stack Mon Nov 26 2018 11:16:36 GMT+0900 (日本標準時) Resource creation Initiated ⠼ Updating resources in the cloud. This may take a few minutes... ... ✔ All resources are updated in the cloud
完了するとCognitoが作成されていることを確認できます。
また、パスワードの設定などがカスマイズされていることも確認できます。
プロジェクトの src/aws-exports.js
にユーザープールのIDが保存されます。
AppSyncの作成
続けてAppSyncを作成してみます。
認証方法は先ほど作成したCognitoを用いたいと思います。
$ amplify add api ? Please select from one of the below mentioned services GraphQL ? Provide API name: amplifyvuedemo ? Choose an authorization type for the API Amazon Cognito User Pool Use a Cognito user pool configured as a part of this project ? Do you have an annotated GraphQL schema? No ? Do you want a guided schema creation? true ? What best describes your project: ? What best describes your project: One-to-many relationship (e.g., “Blogs” with “Posts” and “Comments”) ? Do you want to edit the schema now? No ? Press enter to continue GraphQL schema compiled successfully. Edit your schema at ***/amplify-vue-demo/amplify/backend/api/amplifyvuedemo/schema.graphql Successfully added resource amplifyvuedemo 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
今回はSchemaを定義せずにチュートリアルで用意されているブログ用のスキーマを選択しました。
チュートリアルではデータソースにDynamoDBが使われているので、AppSyncと直接同期することができます。
完了するとamplify/backend/api/{API name}/build/schema.graphql
が作成されて、スキーマが定義されます。
schema.graphql
type Blog @model { id: ID! name: String! posts: [Post] @connection(name: "BlogPosts") } type Post @model { id: ID! title: String! blog: Blog @connection(name: "BlogPosts") comments: [Comment] @connection(name: "PostComments") } type Comment @model { id: ID! content: String post: Post @connection(name: "PostComments") }
Resolverが amplify/backend/api/{API name}/build/resolver
以下に格納され、リソースの詳細情報が保存されています。
作成したAppSyncをAWSに反映しましょう。
$ amplify push | Category | Resource name | Operation | Provider plugin | | -------- | --------------- | --------- | ----------------- | | Api | amplifyvuedemo | Create | awscloudformation | | Auth | amplifyauthdemo | No Change | awscloudformation | ? Are you sure you want to continue? true GraphQL schema compiled successfully. Edit your schema at ***/amplify-vue-demo/amplify/backend/api/amplifyvuedemo/schema.graphql ? Do you want to generate code for your newly created GraphQL API (Y/n) ? Do you want to generate code for your newly created GraphQL API Yes ? Choose the code generation language target ? Choose the code generation language target javascript ? Enter the file name pattern of graphql queries, mutations and subscriptions (src/graphql/**/*.js) ? 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 (Y/n) ? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes ⠇ Updating resources in the cloud. This may take a few minutes... UPDATE_IN_PROGRESS amplifyvuedemo-20181126103438 AWS::CloudFormation::Stack Mon Nov 26 2018 11:34:52 GMT+0900 (日本標準時) User Initiated UPDATE_IN_PROGRESS authamplifyauthdemo AWS::CloudFormation::Stack Mon Nov 26 2018 11:34:57 GMT+0900 (日本標準時) ... ✔ Generated GraphQL operations successfully and saved at src/graphql ✔ All resources are updated in the cloud GraphQL endpoint: https://***.appsync-api.ap-northeast-1.amazonaws.com/graphql
言語を選択してコード生成ができます。今回はJavaScriptを選択しています。
完了するとプロジェクトに以下のファイルが生成されています。
src/graphql
.graphqlconfig.yml
.graphqlconfig.yml
はAppSyncの情報が格納されています。
src/graphql
は定義されているクエリやミューテーションが文字列として格納されている。
使用するときにクエリを選ぶことができる。
Vueパッケージをインストール
Vueのライブラリとして使用するためのパッケージをインストールする
$ npm i aws-amplify aws-amplify-vue
これでAmplifyをライブラリとして使う準備ができました。
ユーザーの認証画面を作成する
AmplifyにはいくつかUIが用意されています。
認証では Authenticator
コンポーネントを組み込むことで認証フローの実装をスキップできます。
認証情報はストア上で行うため、先にストアの設定を行います。
store.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { user: null }, mutations: { setUser(state, user) { state.user = user } }, actions: { } })
認証情報はページ遷移ごとにチェックする必要があるため、ルーティングに認証チェックフローを実装します。
Vue Routerと一緒にAmplifyのライブラリのインポートを行います。
router.js
import Vue from 'vue' import Router from 'vue-router' import Home from '../views/Home.vue' import AmplifyStore from '../store' import { AmplifyEventBus, AmplifyPlugin, components } from 'aws-amplify-vue' import * as AmplifyModules from 'aws-amplify' Vue.use(Router) Vue.use(AmplifyPlugin, AmplifyModules)
認証状態がパスワードチェック前なのかサインイン前なのかなどをEventBusで確認します。
router.js
let user; getUser().then((user) => { if (user) { router.push({path: '/'}) } }) AmplifyEventBus.$on('authState', async (state) => { if (state === 'signedOut'){ user = null; AmplifyStore.commit('setUser', null); router.push({path: '/auth'}) } else if (state === 'signedIn') { user = await getUser(); router.push({path: '/'}) } }); function getUser() { return Vue.prototype.$Amplify.Auth.currentAuthenticatedUser().then((data) => { if (data && data.signInUserSession) { AmplifyStore.commit('setUser', data); return data; } }).catch(() => { AmplifyStore.commit('setUser', null); return null }); }
ルーティング前にユーザーが設定されているかで、ログイン画面にルーティングするかを決める処理を実装します。
router.beforeResolve(async (to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { user = await getUser(); if (!user) { return next({ path: '/auth', query: { redirect: to.fullPath, } }); } return next() } return next() })
Amplifyが用意しているAuthenticatorコンポーネントを /auth
に宣言します。
const router = new Router({ mode: 'history', base: process.env.BASE_URL, routes: [ { path: '/', name: 'home', component: Home }, { path: '/auth', name: 'auth', component: components.Authenticator } ] })
ローカル上で起動し http://localhost:8080/auth
にアクセスするとログイン画面にルーティングされます。
これで認証機能を作成することができました。
Authenticator
コンポーネントはストアのユーザー情報とCogntioにリクエストした認証状態を確認し、適切なルーティングを行ってくれます。
GraphQLにリクエストしてみる
AppSyncのリソースと同時に作成された src/graphql/
を使うことでリクエストを簡単に実装できます。
はじめに必要なライブラリをインポートしましょう。
import { API, graphqlOperation } from 'aws-amplify' import * as mutaions from '@/graphql/mutations'
メソッドにGraphQLへのリクエストを持ったコンポーネントを実装します。
export default { name: 'CreatePost', data: function() { return { postData: { author: '', content: '' }, myPost: '' } }, methods: { createPost: function () { API.graphql(graphqlOperation(mutaions.createPost, this.postData )) .then((response) => { console.log(response) this.myPost = response }) .catch((err) => { console.log(err) }) } } }
graphqlOperation
に使用するクエリとパラメータを指定したオブジェクトをAPI.graphql
関数に渡しています。
クエリを変更するだけで、リクエストを変えることができます。
実装の全体はGitHubにリポジトリを作成しているのでこちらをご確認ください。
まとめ
AmplifyをVueに組み込んでみました。
CLIでAWSリソースを作るのは便利ですが、CI/CDとの兼ね合いが難しそうです。
VueのAmplify UIはReactに比べてまだデザインの拡張性は難しいですが、簡単にAWSとの連携を実装できます。
AmplifyはOSSなので欲しい機能などはPRを出してみたいです。
参考: