記事の目的
aws-amplify の v6 から Next.JS に寄り添った機能を提供するようになり、我が社で使っていた amplify を v5->v6 へアップグレードすることになった。
その際に実際に起きた変更点や docs からは掴みにくい点、かかった時間について述べる
ちなみに変更ファイル数 61, 変更行数 約30k行, 作業時間は 25時間 ほどであった.
変更行の内訳
-
package-lock.json
19k 行 (63%) -
amplify が自動生成する graphQL の query や 型定義
9.7k 行 (32%) - 残り, 手動による書き換え 1k 行 (3%)
package.json
一部抜粋
変更の前後で package.json
の dependencies
がどう変わったかを載せる
- "@aws-amplify/api": "^5.1.0",
- "@aws-amplify/api-graphql": "^3.2.0",
+ "@aws-amplify/api-graphql": "^4.1.4",
- "@aws-amplify/storage": "^4.5.17",
- "@aws-amplify/ui": "^5.6.1",
- "@aws-amplify/ui-react": "^4.6.1",
+ "@aws-amplify/adapter-nextjs": "^1.2.3",
+ "@aws-amplify/ui-react": "^6.1.12",
+ "@aws-crypto/sha256-js": "^5.2.0",
- "aws-amplify": "^5.2.1",
+ "aws-amplify": "^6.3.4",
- "next": "13.4.2",
+ "next": "^14.2.3",
point
@aws-amplify/api, @aws-amplify/storage といったように、 aws-amplify
package に付随した package を一部インストール不要になり、 aws-amplify
内に組み込まれるようになった. ただし一部残ったものもある. プロジェクトによっては不要かもしれない
-
@aws-amplify/api-graphql
- このパッケージから排出される
GraphQLOptionsV6
,GraphQLResult
が必要だっためインストール
- このパッケージから排出される
-
@aws-amplify/adapter-nextjs
- Next のサーバーサイドでの処理を遂行するための機能を提供したもの
- request や cookies をもとに認証をサーバーで行なうための機能がメイン
-
@aws-amplify/ui-react
- front で認証結果を React.Provider を活用して早期アクセスを可能にするもの(
<Authenticator.Provider>
)。自前で Provider を書いたりしたら別に要らない - amplify/ui を使っていたらいるのかも? amplify/ui は使っていないので詳しくない
- front で認証結果を React.Provider を活用して早期アクセスを可能にするもの(
-
@aws-crypto/sha256-js
-
@aws-amplify/ui-react
の内部で使っているらしく、明示的に install しないとエラーになった
-
migration 作業内容
migration に費やした時間は主に以下であった
- v5 で提供された package を v6 のものへ変更していくコードの変更
- 元のままでは動かなくなった jest の設定の修正
- SSR コードの書き換え
コードの変更
基本的には下記の migration guide に従って書き換えていくだけで大抵は対応できる.
graphQL API はなぜか上記と同じように migration guide を用意してくれてなかったので、このセクションでは graphQL の migration を一部紹介と、上記の docs からはわかりにくかった変更内容を紹介する
graphQL の migration
公式の docs はないが、他の package の migration を踏んだら、 graphQL の migration 方法もなんとなく見当がつくので、そこまで困らないと思う.
API call 方法
v5
import {API} from 'aws-amplify';
import * as mutations from './graphql/mutations';
const todoDetails = {
name: 'Todo 1',
description: 'Learn AWS AppSync'
};
API.graphql({
query: mutations.createTodo,
variables: { input: todoDetails }
})
v6
import { generateClient } from 'aws-amplify/api';
import * as mutations from './graphql/mutations';
const client = generateClient();
const todoDetails = {
name: 'Todo 1',
description: 'Learn AWS AppSync'
};
const newTodo = await client.graphql({
query: mutations.createTodo,
variables: { input: todoDetails }
});
client 生成時 (generateClient
) にデフォルトとなる認証方式を設定できたりして、 API client の作成がちょっと楽になった.
その他わかりにくかった点
apiURLの取得方法
amplify の環境を pull したときにできる config を用いて backend リソースへアクセスするための URL の取得方法. どこにも変更書いてないと思う
v5
import {API} from 'aws-amplify';
const apiUrl = await API.endpoint('someApi')
v6
import {Amplify} from 'aws-amplify';
const apiUrl = Amplify.getConfig().API?.REST?.someApi.endpoint;
session token の取得方法
これはどこかに書いてたかも
v5
import {API, Auth} from 'aws-amplify';
const token = await Auth.currentSession()).getIdToken().getJwtToken()
const auth = `Bearer ${token}`
v6
import {fetchAuthSession} from 'aws-amplify/auth';
const token = await fetchAuthSession().tokens?.idToken?.toString()
const auth = `Bearer ${token}`
jest.config の変更
我々の config の設定がまずかったのか、既存の以下の jest の設定のままでは、エラーが出るようになった
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
/** @type {import('jest').Config} */
const customJestConfig = {
testEnvironment: 'jest-environment-jsdom',
globals: {
'ts-jest': {
useESM: true,
},
},
preset: 'ts-jest/presets/default-esm',
transform: {},
extensionsToTreatAsEsm: ['.tsx', '.ts'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
uuid: require.resolve('uuid'),
},
};
module.exports = createJestConfig(customJestConfig);
error message
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/builds/strategitjp/joint/basis/ui/hosting/node_modules/rxjs/dist/esm5/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { Observable } from './internal/Observable';
^^^^^^
SyntaxError: Unexpected token 'export'
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1505:14)
ts-jest
の設定を見直したりしてみたりしたが変わらず、これを参考に transformIgnorePatterns
を変えてみたが変わらずエラー。
初心に戻って Next が公式で提供している jest の設定にしてみたら通過。
preset
がよくなかったのかな・・・?
jest の config は CJS, ESM の歴史も把握しとく必要があってなかなか複雑
行き詰まったら公式に倣うこと
SSR の設定
以下が公式の migration
素晴らしいほどに Next の SSR がしやすくなっている.
request, response instance を withSSRContext
に渡してサーバー処理を行うのが v5 だったが、 cookie だけでその処理を実現できるようになっており、 server component をかけるようになった。
ただし、なぜか我々のコードでは以下のエラーが出ていた
No current user
underlyingError: Error: Network error
が、原因は msw の設定がまずかったらしい。
msw はその時点で使っていなかったので、削除することで無事 SSR できるようになった.
まとめ
変更点はそれなりにあるが、総じてみると、「変更の仕方を知ってれば全然大したことない変更量だな」と感じた。
プロジェクトの依存パッケージのアップグレードは課題として挙げられがちだが、今回の amplify のアップグレードはかなり楽な方であったであろう。(何より詰まったら AWS がサポートしてくれるので )
さて、我々にはまだ mantine の v6 -> v7 作業が残っている...