【key-front】Next.js App Routerの素振り(環境構築・デプロイ・テスト・カタログ)
モチベーション
- 毎週木曜日Slackのkey_frontチャンネルでハドル機能を使いお題に対してメンバー同士ディスカッションをする時間を15〜30分程度設けている
- 今回はNext.js App Routerについて取り上げる
- ファシリテーターは筆者なので、事前に読み込んで気になった点などをスクラップに投げていく
- 開催日は○○/○○(木)で最終的に議事録として結論をまとめる
過去に開催した関連してそうな内容
環境構築
$ npx create-next-app@latest
# 画像添付の操作
$ cd app-name
$ code .
$ npm run dev
sampleリポジトリを作る程度なら以下はスキップする。
もしclientリポジトリを作る場合は本スクラップに記述している内容を消化すること。
Voltaでバージョンのピン留めをする
$ volta pin node@20.15.0
$ volta pin npm@10.7.0
ディレクトリ構成を整える
チームで検討する。
必要なければ個人の好みで整える。
.vscode/settings.jsonの設定を追加をする
以下はextenstions.jsonの記事になるがsettings.jsonも設定する。
tsconfig.jsonの設定を追加する
tsconfig.jsonはstrictestを導入して硬めに行く。
ついでにエイリアスも設定しておく。
$ npm install -D @tsconfig/next
$ npm install -D @tsconfig/strictest
静的解析の設定を追加する
ESLint、Prettier、Stylelint、コミット品質担保(husky + lint-staged)の設定をする。
ESLint周りは以下の記事にまとめている。
CSS周りを整える
基本はRadix UI(primitives) + CSS Modulesで進める。UIコンポーネントではなくHeadless UIコンポーネントを使用する理由は以下の記事で触れている。Headless UIコンポーネントはArk UIやReact Ariaなどいくつか素振りをしてみたが感触が良かったのがRadix UIだったというくらい温度感なので今後別のHeadless UIコンポーネントに変わる可能性はあり。
PR TIMES社とmicroCMS社がテックブログでRadix UI(primitives)について触れているので添付する
リセットCSSは以前、制作チームからおすすめしてもらったものを使用する
bundle-analyzerを導入する
後々めんどくさくなって後回しになるので早めに導入する。
Next.jsの公式ドキュメントに案内があるので、こちらの案内に従う。
テストを導入する
react-testing-libraryを導入する。
詳細は後続のスクラップで触れている。
カタログを導入する
Storybookを導入する。
詳細は後続のスクラップで触れている。
Vercel
ホスティングはVercelを選択した。
本番環境が遅い
- 開発環境ではprefetchがなし(以下参照・実際に確認済み)である程度早く処理されていたのに逆にprefetchされる本番環境では異様に遅い
Prefetching happens when a <Link /> component enters the user's viewport (initially or through scroll). Next.js prefetches and loads the linked route (denoted by the href) and its data in the background to improve the performance of client-side navigations. Prefetching is only enabled in production.
- ネットワークタブを見るとcontent downloadにかなり持って行かれている
- bundle-analyzerで確認してみたがバンドルサイズに問題はなさそう
- 開発環境で
npm run build && npm run start
を実行しprefetchできる環境で試してみた。これは期待値の速さになっていた
→ 恐らくVercel周りの設定で何かやらかしているはず
- 上記の理由からVercel周りで調査を進めて、以下の記事を見つけた。本番環境が異様に遅い原因はVercelのリージョンがワシントンDCになっていたからだった。東京リージョンに修正して完了。
- リージョンが違うだけでここまでパフォーマンスに影響が出るのかと知った
ドキュメントを見たらServerless FunctionはデフォルトでワシントンDCとして設定されるとのこと
By default, Serverless Functions execute in Washington, D.C., USA (iad1) for all new projects to ensure they are located close to most external data sources
Vercel Functionsの詳細
- 何も設定していないとVercel Functions・API Routes・Server Rendering・ISRの向きがワシントンDCになるのか
Speed Insights・Web Analyticsの導入
- Vercelをいじっていく中でVercel謹製のSpeed InsightsとWeb Analyticsがあることを知った
- どのプランでも使うことができる、詳細は下記記事から確認する
- 極端な話、VercelのダッシュボードからWeb Vitalsの確認もウォッチできるからlighthouse使う必要がなくなるのかな。一旦運用してみてる。
react-testing-libraryを導入する
以下はReact + Viteの時のセットアップ等だったのでNext.jsで組み込む時に変更があればメモしていく
Next.jsのtesting-libraryのドキュメント
導入は以下に沿って進める
ドキュメントにインストールするパッケージの案内があるのでそちらに従う。npm init jest@latest
でjestのセットアップが可能だが手直しが発生するのでマニュアルセットアップで対応する
ドキュメントで紹介されているパッケージ群
とりあえずドキュメントで紹介されているパッケージのインストールをする
$ npm install -D \
jest \
jest-environment-jsdom \
@testing-library/react \
@testing-library/jest-dom
追加で必要なパッケージパッケージ群
足りないパッケージを追加していく
$ npm install -D \
ts-jest \
@types/jest \
ts-node \
@testing-library/user-event \
next-router-mock
next-router-mock
next/linkのモックを作るために使用
この時にtsファイルにjestを書くと名前空間でエラーは発生するので次のts-jestと@types/jestを導入した
ts-jest & @types/jest
READMEに沿ってts-jestと@types/jestを導入した
ts-node
jest.config.jsではなくjest.config.tsで動かすためにはts-nodeが必要になるため導入した(後でPrismaも入れる想定だったのでどちらにせよ必要になるので)
To read TypeScript configuration files Jest requires ts-node. Make sure it is installed in your project.
@testing-library/user-event
fireEventではなくuserEventを使いたいため
マニュアルセットアップ
マニュアルセットアップはこちらを参照する
preset: ts-jest
とは?
testEnvironmentとは?
import type { Config } from 'jest'
// eslint-disable-next-line import/extensions
import nextJest from 'next/jest.js'
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
const config: Config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
preset: 'ts-jest',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/app/$1',
},
// Add more setup options before each test is run
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config)
// Optional: configure or set up a testing framework before each test.
// If you delete this file, remove `setupFilesAfterEnv` from `jest.config.js`
// Used for __tests__/testing-library.js
// Learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom'
react-testing-libraryのルールセットを導入する
ルールが効いているかの検証としてtesting-library/prefer-user-event
を有効にしてfireEventを使用した際に警告が出るか確認する
$ npm install -D eslint-plugin-testing-library
ESLintをオーバーライドさせてテストファイルに対してのみeslint-plugin-testing-libraryを実行する
"overrides": [
{
"files": ["**/?(*.)+(spec|test).[jt]s?(x)"],
"extends": ["plugin:testing-library/react"],
"rules": {
"testing-library/prefer-user-event": "error"
}
}
]
実際にtesting-library/prefer-user-eventで警告が表示されればok
Storybookを導入する
$ npx storybook@latest init
アドオンの追加
ユーザー操作擬似クラスのアドオンを追加する。
全体に反映すると後々楽なのでpreviewのparameterに追加すると良いかも。
エイリアスの設定もやっておく。
Storybookのルールセットを導入する
ESLintをオーバーライドさせてカタログファイルに対してのみeslint-plugin-storybookを実行する
"overrides": [
{
"files": ["*.stories.@(ts|tsx)"],
"extends": ["plugin:storybook/recommended"],
"rules": {
"storybook/hierarchy-separator": "error",
"storybook/default-exports": "off"
}
}
]
実際にstorybook/hierarchy-separatorで警告が表示されればok
みてる