in these days, i prepare the developing envioromnent with aws amplify gen2 and next.js. this is the summary.
install AWS CLI on [https://awscli.amazonaws.com/AWSCLIV2.msi]
Set up authentication credentials
aws configure
AWS Access Key ID: あなたのアクセスキー
AWS Secret Access Key: あなたのシークレットキ
Default region name: 例 ap-northeast-1 (東京)
Default output format: json (Enter でOK)
confirm AWS CLI
aws --version
Install node.js on https://nodejs.org/ja/download
Move to current directory
cd (current directory)
Recreate npm Project / Project Setup
npx create-next-app@latest
Install Amplify Backend and Frontend SDKs in the Next.js Project Root Directory
npm install @aws-amplify/backend
npm install @aws-amplify/data-schema
npm install aws-amplify
npm install @aws-amplify/ui-react
npm install @aws-amplify/backend-cli --save-dev
Create Directories and Files
mkdir amplify
mkdir amplify\data
mkdir amplify\auth
type nul > amplify\backend.ts
type nul > amplify\data\resource.ts
type nul > amplify\auth\resource.ts
Open the created amplify/backend.ts file and add the following content:
// amplify/backend.ts
import { defineBackend } from '@aws-amplify/backend';
// 認証リソースをインポート
// aws公式サイトを見ても.tsがついていないが、npx ampx sandobxのときにtsがついていないとエラーが出る
import { auth } from './auth/resource.ts';
import { data } from './data/resource.ts';
// The Amplify backend definition.
defineBackend({
auth, // ここにインポートした 'auth' を追加
data, // ここにインポートした 'data' を追加
});
Open the created amplify/data/resource.ts file and add the following content:
// @aws-amplify/backend から必要なモジュールをインポートします。
// a: スキーマ定義のためのヘルパー (例: a.model, a.string)
// defineData: データリソース全体を定義するための関数
// type ClientSchema: フロントエンドでの型付けに使用されるユーティリティ型
import { a, defineData, type ClientSchema } from '@aws-amplify/backend';
// データのスキーマを定義します。これはGraphQLスキーマの定義に相当します。
// a.modelと定義するだけで、query(取得)、mutation(更新)も自動で定義。
const schema = a.schema({
// 'Todo' という名前のデータモデルを定義します。
// これは AWS DynamoDB のテーブルに対応します。
Todo: a.model({
// 'content' というフィールドを定義します。型は文字列 (String) です。
content: a.string(),
// 'isDone' というフィールドを定義します。型は真偽値 (Boolean) です。
isDone: a.boolean()
})
// このモデルに対するアクセス許可(認可ルール)を定義します。
// ここでは、パブリックな API キー (publicApiKey) を持つユーザー(クライアント)にアクセスを許可しています。
//.authorization(allow => [allow.publicApiKey()])
.authorization(allow => [
allow.publicApiKey(),
// 修正後のコード: 認証済みユーザーなら誰でもOK (操作限定はできない)
allow.authenticated()
// もしくは
// allow.private()
])
});
// Used for code completion / highlighting when making requests from frontend
// フロントエンド (Amplify クライアント) でリクエストを行う際、
// スキーマの型補完やハイライト表示に使用するためにエクスポートされる型です。
export type Schema = ClientSchema<typeof schema>;
// defines the data resource to be deployed
// デプロイされるデータリソース(AppSync APIとDynamoDBテーブルなど)を定義し、設定します。
export const data = defineData({
// 上で定義した GraphQL スキーマを設定します。
schema,
// 認証モードを設定します。
authorizationModes: {
// デフォルトの認証モードとして 'apiKey' を設定します。
defaultAuthorizationMode: 'apiKey',
// API Key 認証モードの詳細設定です。
apiKeyAuthorizationMode: {
// API キーの有効期限を30日に設定します。
expiresInDays: 30
}
}
});
Open the created amplify/auth/resource.ts file and add the following content:
// amplify/auth/resource.ts
import { defineAuth, secret } from "@aws-amplify/backend";
/**
* The Amplify Auth resource definition.
*/
export const auth = defineAuth({
loginWith: {
// ユーザー名とパスワードによるログインを有効化
email: true,
},
});
Create Directories and Files
type nul > app\providers.tsx
type nul > app\useAmplifyClient.ts
type nul > components\TodoList.tsx
Open the app/layout.tsx file and add the following content:
// app/layout.tsx
// ★ "use client" はここに書かない(Server Componentのままにする)
import './globals.css' // グローバルCSSのインポート
// 新しく作成した Client Component ラッパーをインポート
import Providers from '../app/providers'
//ここは、ログイン前の画面のroot
export default function RootLayout({
children,
}: {
children: React.ReactNode // ★ childrenを受け取る形式が必須
}) {
return (
<html lang="ja">
<body>
{/* Providers (Client Component) でラップ */}
<Providers>{children}</Providers>
</body>
</html>
)
}
Open the app/page.tsx file and add the following content:
// app/page.tsx
'use client'
import { Authenticator } from '@aws-amplify/ui-react';
import TodoList from '../components/TodoList';// TodoListコンポーネントを切り出す
export default function DashboardPage() {
return (
<Authenticator>
{({ signOut, user }) => (
<main>
<h1>Hello, {user?.username}!</h1>
<TodoList /> {/* 👈 Todoリストコンポーネントを配置 */}
<button onClick={signOut}>サインアウト</button>
</main>
)}
</Authenticator>
);
}
Open the app/providers.tsx file and add the following content:
// app/providers.tsx
'use client' // ★ これをファイルの先頭に記述!
import '@aws-amplify/ui-react/styles.css'
import { Amplify } from 'aws-amplify'
import outputs from '../amplify_outputs.json'
//ここで、Providersコンポーネントを定義している
//React.ReactNodeとは何だろうか、上記のimoprtのどれかに要素が入っているのだろうが
// ここで設定を一回だけ実行する
// SSR環境での二重実行を防ぐための簡易チェック
Amplify.configure(outputs)
export default function Providers({ children }: { children: React.ReactNode }) {
// ここでContext Providerなどを提供してもOK
return <>{children}</>
}
Open the app/useAmplifyClient.ts file and add the following content:
// src/hooks/useAmplifyClient.ts (例)
'use client'
import { useState, useEffect } from 'react';
import { generateClient, Client } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // 👈 パスに注意
// クライアントを生成し、その状態を返すカスタムフック
export function useAmplifyClient() {
// clientの状態を管理し、初期値はnullにする
const [client, setClient] = useState<Client<Schema> | null>(null);
// コンポーネントがマウントされたら、クライアントを生成する
useEffect(() => {
// Amplifyの設定が Providers.tsx で完了していることを期待
setClient(generateClient<Schema>());
}, []);
return client; // client (または null) を返す
}
Open the components/TodoList.tsx file and add the following content:
// app/components/TodoList.tsx (または page.tsx)
'use client'
import { useState, useEffect } from "react";
// スキーマはフック内で使用されるため、ここでは不要(フックが内部でインポートしている)
// import type { Schema } from "../../amplify/data/resource";
// import { generateClient, Client } from "aws-amplify/data";
// 🚨 【重要】Todoリストの処理に必要なSchema型だけはインポートし直す
import type { Schema } from "@/amplify/data/resource";
import { useAmplifyClient } from '@/app/useAmplifyClient'; // 👈 カスタムフックをインポート
export default function TodoList() {
// 🎉 クライアントの初期化ロジックをフックに任せる
// clientにはバックエンドの全情報が入っている
// しかし、clientは読み込み時にnull ->値に変わるが、
// createのタイミングなどそれ以外では不変
const client = useAmplifyClient();
// todosがメモの配列、それをsetTodos関数で更新する
// ()内は初期値で、今回は空配列[]
// <>内はtypescriptの型定義
// Schemaはamplify/data/resource.tsで定義したもの
// プロパティでTodo,typeをたどっている
// ただし、あくまでtodosのリストなので最後に[]をつけている
// でも結局は配列のどの要素も型は同じ
// 型にも引数にも[]をつけて単一の値と区別する
const [todos, setTodos] = useState<Schema["Todo"]["type"][]>([]);
// 以降、ロジックはシンプルになる
// データ取得関数、データベースからデータを読み込む
const fetchTodos = async () => {
if (!client) return;
// await client.models.Todo.list()で返されるオブジェクトのイメージ
// {
// data: [ // 実際のTodoの配列
// { id: "1", status: "牛乳を買う", isDone: false },
// { id: "2", status: "メールをチェック", isDone: true }
// ],
// // その他の情報(トークンなど、データ取得のメタ情報)
// nextToken: null
// }
// 分割代入 上記のうち、dataプロパティだけを取得する
// だからamplify/data/resource.tsで正しく定義する必要あり
const { data: items } = await client.models.Todo.list();
// 以下でitemsを使った状態の更新が行われ、
// 状態が更新されると、UIの更新が行われる(reactの基本機能)
setTodos(items);
};
// 画面読み込み時クライアントがセットされた後、データをフェッチする
// clientが読み込み後にnull ->値に変化することに対応している
// useEffectはUIと関係ない処理の実行に使う
// 二個引数を取っている
// 一つ目は実行したい処理
// 二つ目がトリガー
// これは、読み込み時のclientがnull->値に変わった時の動作
// それ以降はclientはcreateの際も不変
useEffect(() => {
if (client) {
fetchTodos();
}
}, [client]);
// データ作成関数
const createTodo = async () => {
if (!client) return;
// client.models.Todo.createでデータベースにhttpリクエスト
// window.pronpt()はブラウザの標準機能の利用
await client.models.Todo.create({
content: window.prompt("Todo content?"),
isDone: false,
});
fetchTodos();
}
// クライアントが生成されるまでローディング表示をする
if (!client) {
return <div>データを読み込み中...</div>;
}
// {...}:JSX内でJavascriptの式を埋め込み
// key=idはUIには現れないが必須
return (
<div>
<button onClick={createTodo}>Add new todo</button>
<ul>
{todos.map(({ id, content }) => (
<li key={id}>{content}</li>
))}
</ul>
</div>
);
}
execute the sandbox
npx ampx sandbox
when finish sandbox, Ctrl+C, and then npx ampx sandbox delete
reference
in amplify gen2 guide, sandbox can execute hot reload, the change of local code automatically link to AWS console. but it can't be realized in my developing environment. i give it up.
alternately, by executing sandbox again, Ctrl+C and "npx ampx sandbox", the change can reflect to aws console. it can be confirmed at console of AWS AppSync Schema.
Production deployment
- 🖥️ AWSコンソールからのデプロイ手順(推奨) これが、Amplify Gen 2でNext.jsアプリをGitHubと連携させ、CI/CDパイプラインを確立するための最も推奨される手順です。
AWS Amplify コンソールに移動: AWSマネジメントコンソールにログインし、Amplify サービスを開きます。
新しいアプリケーションの作成: 「新しいアプリを作成」または「Deploy an app」を選択します。
ソースコードプロバイダーの選択: 「GitHub」を選択し、指示に従ってGitHubアカウントと連携します。
Top comments (0)