Azure Static WebAppsは、静的なサイトをホスティングするためのMicrosoft Azureのサービスで、つい先日2021年5月に正式リリースされたばかりのサービスです。
プレビューリリースの段階から個人的に使って色々と試していたのですが、正式リリースの直前にルーティングに関して重要なアップデートがありましたのでその辺りを、next.jsのdynamic rooting機能を使う形で解説してみようと思います。
next.jsとは
Vercelが開発している、next.jsはフロントエンド開発用のフレームワークです。設定不要で初期状態でSSRを利用できることで注目されたフレームワークですが、v9.3(2020/3)でSSGへの対応が追加されました。
特徴的な機能として、ファイルベースのルーティングがあります。pages
というディレクトリにファイルを配置することでとても簡単にルーティングの設定をすることができます。
dynamic routing
next.jsはファイルベースでroutingをすることができることはすでに書きましたが、他に dynamic routing という機能があります。
例えば以下のようにファイルを配置すると、[articleId].tsx
を記事詳細ページとして利用できます。
pages
├── _app.tsx
├── _document.tsx
├── article
│ └── [articleId].tsx
├── articles.tsx
└── index.tsx
イメージとしてはmod_rewriteでこんな感じの設定をイメージしてもらえるとわかりやすいかも?
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^article/([0-9A-Za-z]+)$ article/[articleId].html [L]
</IfModule>
dynamic routingを利用することで /article/nextjs
/ /article/azure_static_webapps
のような複数のurlを /article/[articleId].tsx
で表示することができます。
Server Side Generation(SSG)とClient Side Rendering(CSR)
Server Side Rendering(SSR)や、Client Side Rendering(CSR)の場合に、dynamic routingなpageをビルドすると、以下のようなhtmlが生成されます。tsxファイルがhtmlに変わり、 _next
ディレクトリ以下に生成されたjsファイルなどが配置されます。
out
├── 404.html
├── _next
├── article
│ └── [articleId].html
├── articles.html
└── index.html
対して、Server Side Generation(SSG)の場合は少し異なります。前出の[articleId].tsx
をSSGに対応させてみます。今回は簡易的に /article/nextjs
と /article/azure_static_webapps
の2ページを固定で作成してみます。
import React from 'react'
import { NextPage } from 'next'
interface Props {
articleId: string
}
const ArticleDetailPage: NextPage<Props> = (props) => {
return (
<ArticleDetailView {...props} />
)
}
export const getStaticPaths = async () => {
return {
paths: [
{params: {articleId: 'nextjs'}},
{params: {articleId: 'azure_static_webapps'}},
],
fallback: false,
}
}
export const getStaticProps = async ({params} : any) => {
return {
props: {
code: String(params.articleId),
},
}
}
export default ArticleDetailPage
これをビルドすると以下のようなファイルが生成されます。
out
├── 404.html
├── _next
├── article
│ ├── nextjs.html
│ └── azure_static_webapps.html
├── articles.html
└── index.html
さて、ビルドすると上記で説明したような静的なhtmlが吐き出されますが、nextjsの内部のurlは拡張子なしの /article/nextjs
のような形式になります。
このまま何も設定せずにAzure Satatic WebAppsにデプロイすると、トップページから遷移すればdynamic rootingを使用したページも問題なく表示されますが、/article/nextjs
のようなページが表示されている状態で再読み込みをしてしまうと、該当するファイルが存在しないため404になってしまいます。
Azure Static WebAppsのルーティングを設定する
以前は、routes.json
というファイルでの簡易的なルーティング設定しかできませんでしたが、正式リリース時に staticwebapp.config.json
というファイルを利用したルーティング、認証、mimeタイプの設定など色々な設定が可能になりました。
この機能を利用し下記のようなファイルをビルドディレクトリのトップに配置することで、先ほどの問題を解決することができます。
-
CSRの場合
{ "routes": [ { "route": "/article/*", "rewrite": "/article/[articleId].html" } ] }
-
SSGの場合
{ "routes": [ { "route": "/article/nextjs", "rewrite": "/article/nextjs.html" }, { "route": "/article/azure_static_webapps", "rewrite": "/article/azure_static_webapps.html" } ] }
CSRの場合は、staticwebapp.config.jsonは固定で用意すれば良いので public
ディレクトリに入れておけばビルド時に自動でコピーされるので問題ないでしょう。
SSGの場合は少し手間がかかりますが、該当のページの getStaticPaths
内などで staticwebapp.config.json
を動的に生成する処理を実装する必要があります。
まとめ
以上、nextjsのdynamic routingを使用したサイトをAzure Static WebAppsで利用する方法を簡単に説明してみました。
プレビュー時代には個人的なサイトでのみ利用していましたが、現在構築中のサービスでは本格的に利用を進めています。
Azure Static WebAppsはフロントエンドアプリを配信するにはとても便利なサービスですので、ぜひ試してみてください。