aws-amplify と @aws-amplify/ui-react モジュールを v6 にアップデートしてみた

こんにちは、広野です。

手持ちの React アプリで aws-amplify と @aws-amplify/ui-react モジュールのバージョン 5 を使用していたのですが、バージョン 6 にアップデートしてみました。アプリ内の設定フォーマットや、組み込みの AWS サービス呼び出し用モジュールに変更があったので結構手直しが入りました。ですがドキュメントから情報を探せば何とかなりました。

公式のドキュメントはこちらです。

変更点

私が経験した限りの変更点です。React アプリから以下の AWS サービスを呼び出していたので、その部分の紹介のみとなることをご了承ください。以降、それぞれの変更箇所にブレークダウンしていきます。

  • Amazon Cognito
  • Amazon S3
  • AWS AppSync
  • Amazon Kinesis Data Firehose

aws-amplify モジュールの設定は Amplify.configure というコードでアプリ内に記述します。これまで、連携する AWS サービスごとに設定フォーマットがバラバラだったので、それらが統一された感じがします。それに伴ってかわかりませんが、アプリ内で実際にサービスを呼び出すときの命令コードも変更が入っています。大きな仕様変更と言うよりは、書き方を変えただけという感じでした。

(共通) Amplify.configure の設定

App.js に記述していた設定に変更が入っています。特に Amazon Kinesis Data Firehose 用の設定が大きく変わりました。変更前と変更後のコードを記載し、変更箇所に赤線を引いておきます。

※パラメータは環境変数 (process.env.***) を使用しています。
※記述方法はいくつかのパターンがあります。

  • 変更前
import React from 'react';
import { Amplify, Analytics, AWSKinesisFirehoseProvider } from 'aws-amplify';

//Cognito, S3, AppSync 連携設定
Amplify.configure({
  Auth: {
    userPoolId: process.env.REACT_APP_USERPOOLID,
    userPoolWebClientId: process.env.REACT_APP_USERPOOLWEBCLIENTID,
    identityPoolId: process.env.REACT_APP_IDPOOLID,
    region: process.env.REACT_APP_REGION
  },
  Storage: {
    AWSS3: {
      bucket: process.env.REACT_APP_AMPLIFYSTORAGE,
      region: process.env.REACT_APP_REGION
    }
  },
  aws_appsync_graphqlEndpoint: process.env.REACT_APP_APPSYNC,
  aws_appsync_region: process.env.REACT_APP_REGION,
  aws_appsync_authenticationType: "AMAZON_COGNITO_USER_POOLS"
});
//Kinesis Data Firehose 連携設定
Analytics.addPluggable(new AWSKinesisFirehoseProvider());
Analytics.configure({
  AWSKinesisFirehose: {
    region: process.env.REACT_APP_REGION,
    bufferSize: 1000,
    flushSize: 100,
    flushInterval: 5000, // 5s
   resendLimit: 5
  }
});
  • 変更後
import React from 'react';
import { Amplify } from 'aws-amplify';

//Cognito, S3, AppSync, Kinesis Data Firehose 連携設定
Amplify.configure({
  Auth: {
    Cognito: {
      userPoolId: process.env.REACT_APP_USERPOOLID,
      userPoolClientId: process.env.REACT_APP_USERPOOLWEBCLIENTID,
      identityPoolId: process.env.REACT_APP_IDPOOLID
    }
  },
  Storage: {
    S3: {
      bucket: process.env.REACT_APP_AMPLIFYSTORAGE,
      region: process.env.REACT_APP_REGION
    }
  },
  API: {
    GraphQL: {
      endpoint: process.env.REACT_APP_APPSYNC,
      region: process.env.REACT_APP_REGION,
      defaultAuthMode: 'userPool'
    }
  },
  Analytics: {
    KinesisFirehose: {
      region: process.env.REACT_APP_REGION,
      bufferSize: 1000,
      flushSize: 100,
      flushInterval: 5000, // 5s
      resendLimit: 5
    }
  }
});

Amazon Cognito

@amplify-ui/react と Amazon Cognito を連携させるコードは、かなり変わりました。必要な情報が公式ドキュメント内に分散されて書かれていたので、繋ぎ合わせるのに苦労しました。

私の場合は useAuthenticator を使用しているので、その記述の限りになりますこと、ご了承ください。useAuthenticator で Amazon Cognito の認証を経て、ユーザーの情報やトークンを取得する仕様が変わりました。

  • 変更前
import React from 'react';
import { useAuthenticator } from '@aws-amplify/ui-react';

const { user, signOut } = useAuthenticator((context) => [context.user]);

この記述だけで、以下の情報が取れました。user の中に全て格納されていました。

  1. ユーザー名(メールアドレス)
  2. 所属 Cognito グループ → アプリ内権限分けで使用
  3. ID トークン (Base64 エンコード) → API Gateway の Cognito オーソライザーで使用
  • 変更後
import React, { useState, useEffect } from 'react';
import { useAuthenticator } from '@aws-amplify/ui-react';
import { fetchAuthSession } from 'aws-amplify/auth';

const { user, signOut } = useAuthenticator((context) => [context.user]);

//ステート定義
const [username, setUsername] = useState();
const [authToken, setAuthToken] = useState();
const [groups, setGroups] = useState();

//セッション情報取得
const getSession = async () => {
  const { tokens } = await fetchAuthSession();
  setUsername(tokens?.idToken?.payload.email);
  setGroups(tokens?.idToken?.payload["cognito:groups"]);
  setAuthToken(tokens?.idToken?.toString());
};

useEffect(() => {
  getSession();
}, []);

変更前の記述だけでは欲しいユーザー情報またはセッション情報が取得できないため、赤線部分を追記しています。平たく言うと user の中にユーザーの所属グループや ID トークンは入らなくなりました。そのため、 fetchAuthSession というモジュールを新たに追加しています。※他の取得方法もありますので一例です。

  1. ユーザー名: tokens?.idToken?.payload.email ※メールアドレスをユーザー名にしているため。ユーザー名は user からも取れる。
  2. 所属 Cognito グループ: tokens?.idToken?.payload[“cognito:groups”]
  3. ID トークン: tokens?.idToken?.toString()

Amazon S3

Amazon S3 バケットに JSON データを送信し、ファイルとしてアップロードしておりました。当時の記事は以下です。これに対して書き方の変更が入りました。動作仕様は変わっていないように見えます。

  • 変更前
import { Storage } from 'aws-amplify';

//AmplifyStorageにJSONデータを転送
const putFile = async () => {
  try {
    await Storage.put(
      "data.json", //S3に送信したデータファイルに付けるオブジェクト名
      jsonData, //S3に送信したいJSONオブジェクトのデータ
      {
        level: "private", //private権限のフォルダに格納する
        progressCallback(progress) {
          setProgress(progress.loaded/progress.total);
        }
      }
    );
  } catch (error) {
    alert("File uploading error occurred: " + error);
  }
};
  • 変更後
import { uploadData } from 'aws-amplify/storage';

//AmplifyStorageにJSONデータを転送
const putFile = async () => {
  try {
    const result = await uploadData({
      key: "data.json",
      data: JSON.stringify(jsonData), //Blobまたはstring等でないと送れなくなった
      options: {
        accessLevel: "private",
        onProgress: ({ transferredBytes, totalBytes }) => {
          if (totalBytes) {
            setProgress(transferredBytes / totalBytes);
          }
        }
      }
    }).result;
  } catch (error) {
    alert("File uploading error occurred: " + error);
  }
};

AWS AppSync

React アプリから AWS AppSync 経由でデータのやり取りをしていました。当時の記事は以下です。これに対して少しだけ書き方の変更が入りました。動作仕様は変わっていないように見えます。

  • 変更前
import { API } from 'aws-amplify';
import gql from 'graphql-tag';

//クエリー
const queryGetChat = gql`
  query queryChatdataByServiceid($serviceid: String!) {
    queryChatdataByServiceid(serviceid: $serviceid) {
      items {
        datetime
        user
        message
      }
    }
  }
`;
//メッセージ取得関数
const getChat = async () => {
  const res = await API.graphql({
    query: queryGetChat,
    variables: {
      serviceid: serviceid
    },
    authMode: "AMAZON_COGNITO_USER_POOLS"
  });
};
  • 変更後
import { generateClient } from 'aws-amplify/api';
import gql from 'graphql-tag';

const client = generateClient();

//クエリー
const queryGetChat = gql`
  query queryChatdataByServiceid($serviceid: String!) {
    queryChatdataByServiceid(serviceid: $serviceid) {
      items {
        datetime
        user
        message
      }
    }
  }
`;
//メッセージ取得関数
const getChat = async () => {
  const res = await client.graphql({
    query: queryGetChat,
    variables: {
      serviceid: serviceid
    }
  });
};

Amazon Kinesis Data Firehose

Amazon Kinesis Data Firehose の場合は、データ型の仕様に変更が入っています。以下変更前、変更後の記述方法の違いを見て頂ければと思います。data は送信する JSON データだと思って下さい。

  • 変更前
import { Analytics } from 'aws-amplify';

Analytics.record({
  data: JSON.stringify(data),
  streamName: process.env.REACT_APP_FIREHOSE_STREAMNAME_ACTIVITYLOG
}, "AWSKinesisFirehose");
  • 変更後
import { record } from 'aws-amplify/analytics/kinesis-firehose';

record({
  data: data,
  streamName: process.env.REACT_APP_FIREHOSE_STREAMNAME_ACTIVITYLOG
});

変更前は data を JSON.stringify でテキストに変更していましたが、変更後は JSON オブジェクトをそのまま送らないとエラーになります。

まとめ

いかがでしたでしょうか。

公式ドキュメントを見ながら四苦八苦して動く状態にできたので、本記事が皆様の参考になれれば幸いです。

著者について
広野 祐司

AWS サーバーレスアーキテクチャを駆使して社内クラウド人材育成アプリとコンテンツづくりに勤しんでいます。React で SPA を書き始めたら快適すぎて、他の言語には戻れなくなりました。サーバーレス & React 仲間を増やしたいです。AWSは好きですが、それよりもAWSすげー!って気持ちの方が強いです。
取得資格:AWS 認定は12資格、ITサービスマネージャ、ITIL v3 Expert 等
2020 - 2023 Japan AWS Top Engineer 受賞
2022 - 2023 Japan AWS Ambassador 受賞
2023 当社初代フルスタックエンジニア認定
好きなAWSサービス:AWS Amplify / AWS AppSync / Amazon Cognito / AWS Step Functions / AWS CloudFormation

広野 祐司をフォローする
クラウドに強いによるエンジニアブログです。
SCSKは専門性と豊富な実績を活かしたクラウドサービス USiZE(ユーサイズ)を提供しています。
USiZEサービスサイトでは、お客様のDX推進をワンストップで支援するサービスの詳細や導入事例を紹介しています。
AWSアプリケーション開発クラウドソリューション
シェアする
タイトルとURLをコピーしました