はじめに
SPAのサイトでは新しいバージョンをデプロイした後でも
ユーザーがページを開き直したりF5更新するまでは前のバージョンが使われ続けます。
デプロイ後に新しいバージョンに強制的に更新したり通知したい場合には少し工夫が必要です。
色々やり方はあると思いますがNext.jsとVercelを使っている場合に恐らく最も簡単な方法を紹介します。
以下のコードではページ遷移をした際に新しくデプロイされているかをチェックし
更新されていればアラートを出します。
_app.tsxもしくはlayout.tsx
useEffect(() => {
const checkForUpdates = async () => {
const res = await axios.get('/api/buildId')
const buildId = res.data.buildId
if (prevBuildId && prevBuildId !== buildId) {
alert('新しいバージョンがリリースされました。ページを更新してください。')
// リロードを促すjsxを表示するステートを更新するか強制リロードする
} else {
// 初回ロード時はセットのみ
setPreviousBuildId(buildId)
}
}
checkForUpdates()
const handleRouteChange = () => {
checkForUpdates()
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
api/buildId.ts
const buildId = (req: NextApiRequest, res: NextApiResponse) => {
res.status(200).json({ buildId: process.env.VERCEL_GIT_COMMIT_SHA })
}
解説
vercelの環境変数に最新のコミットのハッシュを返すものがあったので、それをリビジョンとして使っています。
ページ遷移のタイミングで毎回buildIdを取得しそれが前回取得したものと異なっていればリロード画面を出します。
ページ遷移のタイミングでしかデプロイを検知しないため、フォームの入力中などは対応できませんが
とにかくシンプルにやりたい場合はこれで必要十分だと思います。