【从今天开始使用AWS】使用Amplify来部署React应用程序
首先
我叫YN,一个从30岁未经验开始转行为工程师的编程初学者。谢谢您的阅读。
今天我要介绍的是Amplify,它是一个能够通过结合AWS服务来轻松部署无服务器网页应用以及构建CI/CD流程的工具。
本文通过跟随教程的步骤,总结了作为备忘录的Amplify基本原理的理解。
另外,由于遵循教程的步骤会在部署时遇到建造错误(截至2020年8月),所以我也想一并整理出解决方法。
我們這次所做的
我按照教程,使用Amplify,将以下AWS服务结合起来部署了React应用。
-
- DynamoDB
-
- Cognito
-
- AppSync
-
- S3
- CloudFront
部署React应用程序并创建流水线。
按照教程#1的指示,在GitHub仓库上commit(合并到主分支)后将自动部署到的流水线。
使用Amplify可以自动与AWS的CDN服务CloudFront协同工作,实现无服务器方式部署网站。
进行Amplify的初始设置
请按照第二个教程的步骤来进行Amplify的初始设置。
需要做的事情有以下三个步骤。
- AmplifyCLIをローカルPCにグローバルインストール
$ npm install -g @aws-amplify/cli
AWSアカウントの紐付け(解説動画あり。
こちらの記事も参考にさせていただきました。)
$ amplify configure
- AWSバックエンドのセットアップ
$ amplify init --appId [your-app-id]
使用Cognito在网页上实现登录功能。
按照教程3的步骤继续操作。
通过使用Amplify,您可以轻松地将React应用与Cognito进行集成,并实现令人惊叹的用户管理功能。
需要做的事情有以下三点。
- Amplifyライブラリのインストール(ルートディレクトリでnode_modulesに追加)
$ npm install aws-amplify @aws-amplify/ui-react
- Amplifyを使って認証機能の追加
$ amplify add auth
$ amplify push --y
通过上述操作,将生成后台配置文件,并将aws-exports.js添加到/src目录中。
- Reactに認証機能コンポーネントを追加
通过在前端导入aws-exports.js文件,可以将Amplify的后端和React应用连接起来。
// 下記をimport
import Amplify from 'aws-amplify';
import config from './aws-exports';
Amplify.configure(config);
import React from 'react';
import logo from './logo.svg';
import './App.css';
// 下記lコンポーネントをinportしてwrapする
import { withAuthenticator, AmplifySignOut } from '@aws-amplify/ui-react'
function App() {
return (
<div className="App">
<header>
<img src={logo} className="App-logo" alt="logo" />
<h1>We now have Auth!</h1>
</header>
<AmplifySignOut />
</div>
);
}
export default withAuthenticator(App);
在这里实施的用户管理信息可以在Cognito的控制台页面上进行操作。
当你将其合并到远程的主分支后,更改将自动反映在web页面上进行部署。然而,在此状态下可能会出现构建错误,因此接下来我将总结解决方法。
解决构建错误
按照教程的步骤进行操作,由于构建错误导致部署失败,所以在这里总结解决方法。
从控制台界面上,需要对构建进行以下三个附加设置。
- フロントエンドでバックエンドをデプロイする
- フロントエンドでバックエンドリソースをデプロイするためのアクセス許可
- ビルド設定をAmplify CLIの最新版に更新
使用GraphQL-API来将React应用程序和数据库进行集成
按照第四个教程的指示,进行GraphQL的初始设置,并与数据库进行协作。
*GraohQL是Facebook开发的Web API,具有高度自由的查询定义,并且可以在一次请求中高效地获得大量数据。它与state的协作容易,并且与React兼容,是一个非常易于使用的API。
以下是需要完成的三个任务。
- GraphQL-APIとデータベースの設定
$ amplify add api
? Please select from one of the below mentioned services: GraphQL
? Provide API name: notesapp
? Choose the default authorization type for the API: API Key
? Enter a description for the API key: demo
? After how many days from now the API key should expire: 7 (or your preferred expiration)
? Do you want to configure advanced settings for the GraphQL API: No, I am done.
? Do you have an annotated GraphQL schema? No
? Do you want a guided schema creation? Yes
? What best describes your project: Single object with fields
? Do you want to edit the schema now? Yes
- GraphQL-APIをApp-Syncにデプロイ
$ amplify push --y
通过上述操作,AWS的AppSync和DynamoDB的后端将自动构建。同时,查询和变更的配置文件将自动生成并添加到/src/graphql目录下。(太棒了)
- GraphQLをつかってReactアプリとデータベースを連携させる
import React, { useState, useEffect } from "react";
import "./App.css";
import { API } from "aws-amplify";
import { withAuthenticator, AmplifySignOut } from "@aws-amplify/ui-react";
import { listNotes } from "./graphql/queries";
import {
createNote as createNoteMutation,
deleteNote as deleteNoteMutation,
} from "./graphql/mutations";
const initialFormState = { name: "", description: "" };
function App() {
const [notes, setNotes] = useState([]);
const [formData, setFormData] = useState(initialFormState);
useEffect(() => {
fetchNotes();
}, []);
async function fetchNotes() {
const apiData = await API.graphql({ query: listNotes });
setNotes(apiData.data.listNotes.items);
}
async function createNote() {
if (!formData.name || !formData.description) return;
await API.graphql({
query: createNoteMutation,
variables: { input: formData },
});
setNotes([...notes, formData]);
setFormData(initialFormState);
}
async function deleteNote({ id }) {
const newNotesArray = notes.filter((note) => note.id !== id);
setNotes(newNotesArray);
await API.graphql({
query: deleteNoteMutation,
variables: { input: { id } },
});
}
return (
<div className="App">
<h1>My Notes App</h1>
<input
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
placeholder="Note name"
value={formData.name}
/>
<input
onChange={(e) =>
setFormData({ ...formData, description: e.target.value })
}
placeholder="Note description"
value={formData.description}
/>
<button onClick={createNote}>Create Note</button>
<div style={{ marginBottom: 30 }}>
{notes.map((note) => (
<div key={note.id || note.name}>
<h2>{note.name}</h2>
<p>{note.description}</p>
<button onClick={() => deleteNote(note)}>Delete note</button>
</div>
))}
</div>
<AmplifySignOut />
</div>
);
}
export default withAuthenticator(App);
使用S3将照片保存到React应用中。
按照教程#5的指示,将React应用程序与S3进行连接,使之能够将照片保存到存储中。
需要做的事情有以下三个。
- GraphQLスキーマの更新
type Note @model {
id: ID!
name: String!
description: String
image: String
}
- S3によるストレージ機能の追加
$ amplify add storage
$ amplify push --y
- ReactアプリとS3を連携させる
import React, { useState, useEffect } from "react";
import "./App.css";
import { API, Storage } from "aws-amplify";
import { withAuthenticator, AmplifySignOut } from "@aws-amplify/ui-react";
import { listNotes } from "./graphql/queries";
import {
createNote as createNoteMutation,
deleteNote as deleteNoteMutation,
} from "./graphql/mutations";
const initialFormState = { name: "", description: "" };
function App() {
const [notes, setNotes] = useState([]);
const [formData, setFormData] = useState(initialFormState);
useEffect(() => {
fetchNotes();
}, []);
async function fetchNotes() {
const apiData = await API.graphql({ query: listNotes });
const notesFromAPI = apiData.data.listNotes.items;
await Promise.all(
notesFromAPI.map(async (note) => {
if (note.image) {
const image = await Storage.get(note.image);
note.image = image;
}
return note;
})
);
setNotes(apiData.data.listNotes.items);
}
async function createNote() {
if (!formData.name || !formData.description) return;
await API.graphql({
query: createNoteMutation,
variables: { input: formData },
});
if (formData.image) {
const image = await Storage.get(formData.image);
formData.image = image;
}
setNotes([...notes, formData]);
setFormData(initialFormState);
}
async function deleteNote({ id }) {
const newNotesArray = notes.filter((note) => note.id !== id);
setNotes(newNotesArray);
await API.graphql({
query: deleteNoteMutation,
variables: { input: { id } },
});
}
async function onChange(e) {
if (!e.target.files[0]) return;
const file = e.target.files[0];
setFormData({ ...formData, image: file.name });
await Storage.put(file.name, file);
fetchNotes();
}
return (
<div className="App">
<h1>My Notes App</h1>
<input
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
placeholder="Note name"
value={formData.name}
/>
<input
onChange={(e) =>
setFormData({ ...formData, description: e.target.value })
}
placeholder="Note description"
value={formData.description}
/>
<input type="file" onChange={onChange} />
<button onClick={createNote}>Create Note</button>
<div style={{ marginBottom: 30 }}>
{notes.map((note) => (
<div key={note.id || note.name}>
<h2>{note.name}</h2>
<p>{note.description}</p>
<button onClick={() => deleteNote(note)}>Delete note</button>
{note.image && <img src={note.image} style={{ width: 400 }} />}
</div>
))}
</div>
<AmplifySignOut />
</div>
);
}
export default withAuthenticator(App);
现在,我们可以将Cognito、AppSync和S3结合起来,部署React应用程序。
最終的に (zuì yī)
通过使用Amplify,您可以轻松部署现代化的无服务器应用程序。AWS可能让编程初学者感到有些高门槛,但我感受到了它非常亲近的特点。
教程上写着可以在”50分钟完成”,但即使是编程初学者也能够在那个时间范围内完成。我相信您能够理解Amplify是一项多么出色的服务。(尽管在处理构建错误方面花了我3天。苦笑)
非常感谢您的阅读。
可以在文章中参考一下我读过的那篇文章。
-
- ビルド失敗時のエラー対処
-
- https://stackoverflow.com/questions/59708481/aws-amplify-deploy-failure-due-to-aws-exports
-
- https://github.com/aws-amplify/amplify-cli/issues/3149
-
- https://docs.aws.amazon.com/ja_jp/amplify/latest/userguide/amplify-console-ug.pdf
-
- https://shimba.io/tatsuyoshi/article/01E13AH3HGHRR0CQC4BNC966MF
-
- https://kahoo.blog/aws-amplify-setup-frontend-and-backend-deploy/
-
- Amplify解説
- https://egghead.io/courses/building-serverless-web-applications-with-react-aws-amplify