🗽

AmplifyUIComponentをSSRすることはできない

2023/12/19に公開

概要

色々試したのですが(2023/12現在)AmplifyStudioのUILibraryで作ったコンポーネントはSSRできませんでした。
https://ui.docs.amplify.aws/react/getting-started/usage/nextjs#app-router

Amplify UI components are interactive and designed to work on the client side. To use them inside of Server Components you must wrap them in a Client Component with "use client".

環境

next@13.5.6 for AppRouter
aws-amplify@6.0.6
@aws-amplify/ui-react@6.0.4
@aws-amplify/adapter-nextjs@1.0.6

経緯

Amplifyっていう良いソリューションがあるらしい!

SSRにも対応してるんだ!デプロイも簡単だな〜

あれれ、FigmaからAmplify経由で作ったComponent入れるとエラーになるぞ...

~300年後~

やっぱり動かなかった
公式にも書いてあったんだ、トホホ...

副産物

AmplifyでNext.js(AppRouter)のSSRをデプロイできた

ComponentはSSRできないけどデータを持ってくることはできるみたいです
簡単にまとめました

  1. generateServerClientUsingCookies()でserverClientを作成する
    server側で動くclient(ややこしい)を作りましょう
utils/server-utils.ts
import { cookies } from "next/headers";
import { generateServerClientUsingCookies } from "@aws-amplify/adapter-nextjs/api";
import config from "../aws-exports";

export const serverClient = generateServerClientUsingCookies({
  config,
  cookies,
});
  1. SSRなページの関数内でGraphQLを呼び出す
    事前にPeopleテーブルとプロパティをAmplifyStudio上で設定済みです
names/page.tsx
export default async function Names() {
  const { data, errors } = await serverClient.graphql({
    query: query.listPeople,
  });

  if (errors) {
    console.error(errors);
    return <div>Error</div>;
  }

  return (
    <div>
      {data.listPeople.items.map((item) => {
        return (
          <div key={item.id}>
            {item.name}
          </div>
        );
      })}
    </div>
  );
}

おわりです。ドキュメント的には...

このままだとエラーが出てデプロイできないのです。
ローカルでbuildしてstartしても再現しないのでちょっとつまづきポイントでした。

Amplifyデプロイ時に出るエラー
ReferenceError: FormData is not defined

ServerにはFormDataが存在せず、serverClientがFormDataを含むのでエラーが出ているらしいのでpackageをinstallします

https://www.npmjs.com/package/form-data

$ npm install form-data

これだけだとなぜかデプロイが通らないので、強制的にform-dataを参照するようにします

global
global.FormData = require("form-data");


やったね

packageをinstallするのは良いとして、globalな値をコードで上書きするのはなかなかhackyで気持ち悪い方法かと思うので、代案をお持ちの方はいただけますと幸いです!

おわり

Discussion