💭
Next.jsのMiddlewareを使ってメンテナンスモードを表示したメモ
Next.js & Vercel は便利ですが、2022年6月時点でVercelはメンテナンスモードを提供していません。なので、Next.jsで自分で実装します。
メンテナンスモードの実装方法は検索すればたくさん出てきますが、今回は Next.js v12 から追加された Middleware を使用して実装してみます。
今回の実装条件は以下です。
- 環境変数の値によって、メンテナンスモードを切り分け
- メンテナンスモードの場合はメンテナンスページを表示
- その際はステータスコード503を返す
とり急ぎ実装したやり方をメモしておきますが、もっといいやり方がありそうな気がします。
手順
1. 環境変数を用意
process.env.NEXT_PUBLIC_MAINTENANCE_MODE === 'true'
2. メンテナンスモード用のエラーページを作成する。
別にエラーページにしなくても良いかもしれないが、503で返すので カスタムエラーページ を作成してみた。
Maintenance.tsx
import styled from '@emotion/styled'
export const Maintenance = () => {
return (
<Container>
<Heading>Under maintenance</Heading>
<Paragraph>
This site is under maintenance.
</Paragraph>
</Container>
)
}
Emotionで実装。CSS等は割愛。
pages/_error.tsx
import { NextPage, NextPageContext } from 'next'
import Error from 'next/error'
import { Maintenance } from './Maintenance'
const ErrorPage: NextPage<{ statusCode: number }> = ({ statusCode }) => {
if (statusCode === 503) {
return <Maintenance />
}
return <Error statusCode={statusCode} />
}
// Ref: https://nextjs.org/docs/advanced-features/custom-error-page#caveats
ErrorPage.getInitialProps = ({ res, err }: NextPageContext) => {
const statusCode = res?.statusCode || err?.statusCode || 404
return { statusCode }
}
export default ErrorPage
カスタムエラーページ のドキュメントを参考に、ステータスコードで場合分け。
(いいかげん getInitialProps
はやめたいのだが...)
3. _app.tsx で表示
どんな書き方でもいいが、ErrorPageにステータスコード503を渡して、環境変数で出し分けする
pages/_app.tsx
const MyApp = () => {
...(省略)
}
const MaintenanceView = () => (
<ErrorPage statusCode={503} />
)
export default process.env.NEXT_PUBLIC_MAINTENANCE_MODE === 'true'
? MaintenanceView
: MyApp
4. Middlewareでレスポンスのステータスコードを503とする
3まででもメンテナンスモードの表示はできるが、ステータスコードが200のままになってしまう。
どうするか悩んだあげく、Middlewareで上書きすることにした。
_middleware.tsx
import { NextResponse } from 'next/server'
export const middleware = () => {
const response = NextResponse.next()
if (process.env.NEXT_PUBLIC_MAINTENANCE_MODE === 'true') {
// Overwrite only status code 503
return new NextResponse(response.body, {
headers: response.headers,
statusText: response.statusText,
url: response.url,
status: 503,
})
}
return response
}
ステータスだけを変更する方法が↑でいいのかはわからないが、とりあえずこれで。
5. チェック
コンポーネントが表示されているか、そしてステータスコードが503になっているかをチェックする。
色々やり方はあるが例えば「cURLでHTTPステータスコードだけを取得する」 でステータスコードを見てみる。
$ curl -LI http://localhost:4200/ -o /dev/null -w '%{http_code}\n' -s
503
OK.
所感
メンテナンスモードのロジックを _middleware.tsx
と _app.tsx
で二回書いていて微妙だし、正直もっといいやり方があると思う。
コメントお待ちしております。
Discussion