v5から v6への移行
このガイドは、withSSRContext を使用する v5 SSR 実装を v6 の新しい Next.js アダプターに移行するのに役立ちます。
ステップ 1: Next.js アダプターをインストール
npm install @aws-amplify/adapter-nextjsステップ 2: サーバー側の構成
Amplify JS v5 の withSSRContext ユーティリティは、Amplify JS v6 では利用できなくなりました。@aws-amplify/adapter-nextjs からエクスポートされた createServerRunner 関数を使用して runWithAmplifyServerContext 関数を作成し、この関数を使用して Next.js アプリのサーバー側から Amplify API 呼び出しを実行する必要があります。
コードベースの utils フォルダに amplifyServerUtils.ts ファイルを作成できます。このファイルで、Amplify CLI によって生成される amplifyconfiguration.json ファイルから Amplify 構成オブジェクトをインポートし、createServerRunner 関数を使用して runWithAmplifyServerContextRunner 関数を作成します。
たとえば、utils/amplifyServerUtils.ts ファイルには以下の内容が含まれる場合があります:
import { createServerRunner } from '@aws-amplify/adapter-nextjs';import config from '@/amplifyconfiguration.json';
export const { runWithAmplifyServerContext } = createServerRunner({ config});ステップ 3: クライアント側の構成
Amplify.configure には 2 つのパラメーターが含まれるようになりました: resourcesConfig と libraryOptions。ssr.true は libraryOptions で送信されるようになりました。
V5
import { Amplify } from 'aws-amplify';import awsExports from '@/aws-exports';
Amplify.configure({ ...awsExports, ssr: true});V6
import { Amplify } from 'aws-amplify';import amplifyConfig from '@/amplifyconfiguration.json';
Amplify.configure( amplifyConfig, { ssr: true });
Amplify.configureへの反復的な呼び出しを避けるために、トップレベルのクライアント側レンダリングされたレイアウトコンポーネントで 1 回呼び出すことができます。詳細については、クライアント側使用用に Amplify ライブラリを構成するを参照してください。
ステップ 4: withSSRContext を runWithAmplifyServerContext に置き換え
サーバーコンテキストにいるときは、必ず /server サブパスから API をインポートしてください。サーバー側でサポートされている API の完全なリストを参照してください。
V5
import { withSSRContext } from 'aws-amplify';import { listTodos } from './graphql/queries';
const getServerSideProps = async ({ req }) => { const SSR = withSSRContext({ req }); const user = await SSR.Auth.currentAuthenticatedUser(); return { props: { user } };};V6
import { getCurrentUser } from 'aws-amplify/auth/server';import { runWithAmplifyServerContext } from '@/utils/amplifyServerUtils';
const getServerSideProps = async ({ req, res }) => { const user = await runWithAmplifyServerContext({ nextServerContext: { request: req, response: res }, operation: (contextSpec) => getCurrentUser(contextSpec) });
return { props: { user } };}注記: Next.js Middleware が v6 でサポートされるようになりました。実装手順は以下で確認できます: Next.js Middleware を使用して認証セッションを管理する
v6 で API カテゴリを使用
Amplify v6 は Next.js サーバーランタイム用の 2 つの特殊化された GraphQL API クライアントを提供します (@aws-amplify/adapter-nextjs/api からインポート)。これは、cookies を使用してユーザートークンを取得するか、NextRequest と NextResponse を使用するかによって使い分けます。v5 で以前利用可能だったものを反映するために、リクエスト/レスポンスベースのサーバークライアントを使用した移行を示します。
まず、amplifyServerUtils ファイルにサーバー側のクライアント生成を追加します:
import { createServerRunner } from '@aws-amplify/adapter-nextjs';import config from '@/amplifyconfiguration.json';
export const { runWithAmplifyServerContext } = createServerRunner({ config});
export const reqResBasedClient = generateServerClientUsingReqRes({ config});次に、サーバー側レンダリングコンポーネントの実装を更新します:
V5
import { withSSRContext } from 'aws-amplify';import { listTodos } from './graphql/queries';
const getServerSideProps = async ({ req }) => { const SSR = withSSRContext({ req }); const { data } = await SSR.API.graphql({ query: listTodos });
return { props: { posts: data.listTodos.items } };};V6
import { reqResBasedClient, runWithAmplifyServerContext} from '@/utils/amplifyServerUtils';import { listTodos } from './graphql/queries';
const getServerSideProps = async ({ req, res }) => { const data = await runWithAmplifyServerContext({ nextServerContext: { request: req, response: res }, operation: async (contextSpec) => { return reqResBasedClient.graphql(contextSpec, { query: listTodos }); } });
return { props: { todos: data.listTodos.items } };};DataStore から GraphQL API クライアントへのサーバーコンテキストでの移行
DataStore は v6 のサーバーコンテキスト内ではサポートされなくなりました。代わりに GraphQL API クライアントを使用する必要があります。
API カテゴリへの正常な移行には、競合解決がどのように機能するかを理解する必要があります。DataStore API は auto-merge 戦略をデフォルトとして使用します。これは以下の例で想定されています。auth-merge 戦略には、標準 GraphQL 操作への次の調整が必要です:
-
GraphQL クエリを実行するときに
_deleted: falseでフィルタリングして、削除されたレコードを無視する必要があります -
GraphQL クエリ、ミューテーション、サブスクリプションの選択セットに
_versionを含める必要があります (amplify 生成ステートメントではデフォルトで含まれています)。
DataStore から GraphQL に操作を移行するときは、リターン構造が異なることも考慮してください: DataStore.query は Todo[] を返しますが、API.graphql リスト操作は { data: { listTodos: { items: Todo[] } } } を返し、DataStore.save は Todo を返しますが、API.graphql 作成/更新操作はそれぞれ { data: { createTodo: Todo } } と { data: { updateTodo: Todo } } を返します。
プロジェクトに GraphQL ミューテーション、クエリ、サブスクリプション、型が含まれていない場合は、以下の amplify cli スクリプトを使用してこれらのファイルを生成できます (API (GraphQL) ドキュメントを参照してください)
amplify codegen statementsamplify codegen typesAPI クライアントのセットアップ
v6 で API カテゴリを使用するの手順に従って、リクエスト/レスポンスベースのサーバークライアントをセットアップしてください。
DataStore.query を API.graphql に置き換え
注記: DataStore で
MULTI_AUTH認証モード戦略を使用していた場合、API.graphql呼び出しで authMode を送信する必要がある場合があります。
V5
import { serializeModel } from '@aws-amplify/datastore/ssr';import { Todo } from '@/src/models';import { withSSRContext } from 'aws-amplify';
export async function getServerSideProps({ req }) { const SSR = withSSRContext({ req }); const todos = await SSR.DataStore.query(Todo);
return { props: { todos: serializeModel(todos), }, };}V6
import { reqResBasedClient, runWithAmplifyServerContext} from '@/utils/amplifyServerUtils';import { listTodos } from '@/graphql/queries';
// Server-Sideconst getServerSideProps = async ({ req, res }) => { const data = await runWithAmplifyServerContext({ nextServerContext: { request: req, response: res }, operation: async (contextSpec) => { const variables = { filter: { _deleted: { eq: false } } }; return reqResBasedClient.graphql(contextSpec, { query: listTodos, variables, authMode: 'apiKey' // May be required when using multi-auth }); } });
return { props: { todos: data.listTodos.items } };};DataStore.save を API.graphql に置き換え
注記: DataStore で
MULTI_AUTH認証モード戦略を使用していた場合、API.graphql呼び出しで authMode を送信する必要がある場合があります。
V5
import { serializeModel } from '@aws-amplify/datastore/ssr';import { Todo } from '@/src/models';import { withSSRContext } from 'aws-amplify';
export async function getServerSideProps({ req }) { const SSR = withSSRContext({ req }); const original = await SSR.DataStore.query(Todo, '123456'); const updatedTodo = await SSR.DataStore.save( Todo.copyOf(original, updated => { updated.lastViewed = new Date() })); return { props: { todo: serializeModel(updatedTodo), }, };}V6
import { reqResBasedClient, runWithAmplifyServerContext} from '@/utils/amplifyServerUtils';import { updateTodo } from '@/graphql/queries';import { GRAPHQL_AUTH_MODE } from
// Server-Sideconst getServerSideProps = async ({ req, res }) => { const data = await runWithAmplifyServerContext({ nextServerContext: { request: req, response: res }, operation: async (contextSpec) => { const todoDetails = { id: '123456', lastViewed: new Date() }; return reqResBasedClient.graphql(contextSpec, { query: updateTodo, variables: { input: todoDetails }, authMode: 'userPool' // May be required when using multi-auth }); } });
return { props: { todo: data.updateTodo } };};