はじめに
NativeScript-Vueを用いてアプリ開発をしています。
その中で、AWS Amplifyと連携する機会があったので紹介していきたいと思います。
アプリの完成イメージ
下部の入力エリアで入力した内容が追加ボタンで追加されます。
タスクのトグルボタンを押下することでタスクに取り消し線と文字が薄くなります。
今回使用する技術を軽く説明
NativeScript-Vue
[NativeScript-Vue](https://nativescript-vue.org/)は、モバイルアプリをJavaScriptで開発するためのOSSです。 モバイルアプリを構築するフレームワークだと、ReactNativeやionicなどReactやAngularを用いることが多いですが、Vue.jsで書けるのがNativeScript-Vueの大きな特徴です。(NativeScriptはAngular)AWS Amplify
[AWS Amplify](https://aws.amazon.com/jp/amplify/)は、モバイルアプリやWebアプリの作成、実装、設定を容易にしてくれるライブラリです。 認証機能やデータの連携を簡単に構築することができます。環境
動作が確認できた環境です。
また、AWS Amplifyを使用する関係でAWSのアカウントが必要となります。
※amplify mockを使用するため、料金はかかりません。
MacOS Mojave: 10.14.6
Node.js: 12.13.1
Python: 3.6.8
Java -version
openjdk version "1.8.0_232"
OpenJDK Runtime Environment Corretto-8.232.09.2 (build 1.8.0_232-b09)
OpenJDK 64-Bit Server VM Corretto-8.232.09.2 (build 25.232-b09, mixed mode)
※Python3系は、NativeScript-Vueを実行するために必要です。
アプリの構築
NativeScript-Vueのセットアップ
vue-cliを利用して、NativeScript-Vueのアプリを構築します。
npm install -g @vue/cli @vue/cli-init
vue init nativescript-vue/vue-cli-template <app-name>
# ? Select a preset (more coming soon) (Use arrow keys)
# ❯ Simple
cd <app-name>
npm install
NativeScriptでは、tns
というコマンドを使用します。
下記のコマンドで、iPhone 11 Pro
のシミュレータが起動します。
もちろん、tns run android
と実行するとAndroidを起動することが可能です。
tns run ios --debug --device 'iPhone 11 Pro'
AWS Amplifyのセットアップ
npm install @aws-amplify/cli
npm i @aws-amplify/api aws-amplify
amplify --version
# 4.18.1
AWS Amplifyを使う準備
webpackの設定を変更する
ここが今回のポイントです。
AWS amplifyをWebのフレームワークで使用した場合には発生しないのですが、Nativescriptで実装した場合、mjs
ファイルを明示的に読み込めるようにしてあげる必要があります。
(省略)
+aliasFields: ["browser"],
+extensions: [".mjs", ".vue", ".ts", ".js", ".scss", ".css"],
-extensions: [".vue", ".ts", ".js", ".scss", ".css"],
(省略)
main.jsにAmplifyのモジュールを使う設定
下記を追加する。
import Amplify, * as AmplifyModules from 'aws-amplify'
import awsmobild from './aws-exports'
Amplify.configure(awsmobild)
Vue.use(AmplifyModules)
APIを作成する
# IAMの作成をしていない方は、aws configureを実行する必要があります。
amplify configure
amplify init
amplify add api
type Message @model {
id: ID!
username: String!
content: String!
}
APIのモックサーバ起動
今回は、amplify mockを利用します。
amplify mockは、作成したAPIをローカル環境で確認することができます。
amplify mock api
# amplify pushをすれば、AppSyncを構築し、DynamoDBにテーブルが作成まで行われます。今回は、mockに留めます。
todoアプリのUIを作成する
ビュー部分
todosという配列をfor文で回して表示しています。
todosが空の時は、メッセージを表示しています。
<template>
<Page>
<ActionBar title="Todo" />
<GridLayout columns="*" rows="*, auto">
<ScrollView class="todo-area" row="0">
<StackLayout v-if="todos.length > 0" class="todos">
<StackLayout v-for="(todo, i) in todos" :key="i" orientation="horizontal" class="todo">
<Label class="content" :class="{ done: todo.isDone }" :text="todo.title" />
<Switch class="check" v-model="todo.isDone" @checkedChange="doneTodo(todo)" />
</StackLayout>
</StackLayout>
<StackLayout v-else id="empty-msg">
<Label text="タスクがありません" />
</StackLayout>
</ScrollView>
<GridLayout columns="*, auto" row="1">
<TextField id="comment-input" col="0" v-model="content" hint="タスクを入力" />
<Button id="submit" col="1" text="追加" @tap="add()" />
</GridLayout>
</GridLayout>
</Page>
</template>
ロジック部分
addでタスクの登録処理、doneTodoでタスクの更新処理、fetchTodosでタスクの一覧を取得しています。
amplifyのmutationsが登録、更新処理。queriesが取得処理です。
<script>
import API, { graphqlOperation } from '@aws-amplify/api';
import { createTodo, updateTodo } from '@/graphql/mutations';
import { listTodos } from '@/graphql/queries';
export default {
data() {
return {
todos: [],
content: ''
}
},
created() {
this.fetchTodos()
},
methods: {
generateId () {
return this.todos.length
},
async add () {
let todo = {
id: this.generateId(),
title: this.content,
isDone: false
}
try {
await API.graphql(graphqlOperation(createTodo, { input: todo }))
} catch (error) {
console.error(error)
} finally {
this.resetInput()
this.fetchTodos()
}
},
async fetchTodos () {
try {
const res = await API.graphql(graphqlOperation(listTodos, { limit: 100 }))
this.todos.push(...res.data.listTodos.items)
} catch (error) {
console.error(error)
}
},
async doneTodo (todo) {
try {
const res = await API.graphql(graphqlOperation(updateTodo, {
input: todo
}))
} catch (error) {
console.error(error)
}
},
resetInput () {
this.content = ''
}
}
}
</script>
ソースコード全体像
<template>
<Page>
<ActionBar title="Todo" />
<GridLayout columns="*" rows="*, auto">
<ScrollView class="todo-area" row="0">
<StackLayout v-if="todos.length > 0" class="todos">
<StackLayout v-for="(todo, i) in todos" :key="i" orientation="horizontal" class="todo">
<Label class="content" :class="{ done: todo.isDone }" :text="todo.title" />
<Switch class="check" v-model="todo.isDone" @checkedChange="doneTodo(todo)" />
</StackLayout>
</StackLayout>
<StackLayout v-else id="empty-msg">
<Label text="タスクがありません" />
</StackLayout>
</ScrollView>
<GridLayout columns="*, auto" row="1">
<TextField id="comment-input" col="0" v-model="content" hint="タスクを入力" />
<Button id="submit" col="1" text="追加" @tap="add()" />
</GridLayout>
</GridLayout>
</Page>
</template>
<script>
import API, { graphqlOperation } from '@aws-amplify/api';
import { createTodo, updateTodo } from '@/graphql/mutations';
import { listTodos } from '@/graphql/queries';
export default {
data() {
return {
todos: [],
content: ''
}
},
created() {
this.fetchTodos()
},
methods: {
generateId () {
return this.todos.length
},
async add () {
let todo = {
id: this.generateId(),
title: this.content,
isDone: false
}
try {
await API.graphql(graphqlOperation(createTodo, { input: todo }))
} catch (error) {
console.error(error)
} finally {
this.resetInput()
this.fetchTodos()
}
},
async fetchTodos () {
try {
const res = await API.graphql(graphqlOperation(listTodos, { limit: 100 }))
this.todos.push(...res.data.listTodos.items)
} catch (error) {
console.error(error)
}
},
async doneTodo (todo) {
try {
const res = await API.graphql(graphqlOperation(updateTodo, {
input: todo
}))
} catch (error) {
console.error(error)
}
},
resetInput () {
this.content = ''
}
}
}
</script>
<style scoped>
ActionBar {
color: white;
}
.todo-area {
background: #E5E5E5;
width: 100%;
height: 100%;
}
.todos {
height: 100%;
margin: 8px;
border-right: 1 solid #ddd;
border-left: 1 solid #ddd;
background-color: #E5E5E5;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.2) inset;
}
.todo {
padding: 4px;
}
.content {
font-size: 20px;
width: 80%;
}
.done {
color: gray;
text-decoration: line-through;
}
.check {
width: 20%;
}
#empty-msg {
text-align: center;
font-size: 16px;
margin-top: 40px;
}
#submit {
margin: 0 auto;
}
#comment-input {
border-width: 1;
border-color: #2E2E2E;
border-radius: 8px;
height: 100px;
}
</style>
アプリの起動(シミュレータ)
tns run ios --debug --device 'iPhone 11 Pro'
おわりに
本来であれば、バックエンドのAPIを構築してデータベースと連携してと実装が、大変なイメージですがAWS Amplifyを使うと簡単にバックエンドが実装できます。
また、アプリもNativeScript-Vueを使えばVue.jsの知識で作れてしまいます。
Vue.jsでアプリ作りたい方、AWS Amplify試してみたい方、NativeScript-Vue + AWS Amplify、是非試してみてください!