【从今天开始使用AWS】使用Amplify来部署React应用程序

首先

我叫YN,一个从30岁未经验开始转行为工程师的编程初学者。谢谢您的阅读。
今天我要介绍的是Amplify,它是一个能够通过结合AWS服务来轻松部署无服务器网页应用以及构建CI/CD流程的工具。
本文通过跟随教程的步骤,总结了作为备忘录的Amplify基本原理的理解。
另外,由于遵循教程的步骤会在部署时遇到建造错误(截至2020年8月),所以我也想一并整理出解决方法。

我們這次所做的

我按照教程,使用Amplify,将以下AWS服务结合起来部署了React应用。

    • DynamoDB

 

    • Cognito

 

    • AppSync

 

    • S3

 

    CloudFront
スクリーンショット 2020-08-02 17.39.04.png

部署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页面上进行部署。然而,在此状态下可能会出现构建错误,因此接下来我将总结解决方法。

解决构建错误

按照教程的步骤进行操作,由于构建错误导致部署失败,所以在这里总结解决方法。
从控制台界面上,需要对构建进行以下三个附加设置。

    フロントエンドでバックエンドをデプロイする
スクリーンショット 2020-08-05 11.05.28.png
    フロントエンドでバックエンドリソースをデプロイするためのアクセス許可
スクリーンショット 2020-08-05 11.44.36.png
    ビルド設定をAmplify CLIの最新版に更新
スクリーンショット 2020-08-05 11.49.39.png

使用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
广告
将在 10 秒后关闭
bannerAds