6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SvelteKit/SSG(adapter-static)で404.htmlを出力する方法

Posted at

はじめに

Jamstack構成でSvelteKit/SSG(adapter-static)を採用しWebサイトを構築する際に、カスタマイズされた404 Not Foundページを表示したい場合には、ホスティングサービスにあわせた404 Not Foundページを出力するように構築する必要がある。

例えばCloudflare Pagesの場合には、リクエストされたページが存在しない場合には、指定されたパスと同一ディレクトリ上の404.htmlを探し、なければディレクトリツリーを検索し続けることで最終的には/404.htmlをレンダリングする仕様になっている。

この404.htmlのスマートな出力方法が意外なことに見当たらなかったため、独自の実装方法で対応した。

注意
本記事の実装例はSvelteKit及びadapter-staticの公式ドキュメントに記載されている方法ではありません。

概要

SvelteKitでは、+error.svelteを実装することで、各routeごとにエラーページをカスタマイズすることができる。
細かなエラー画面の出し分けなどは一旦置いておくとして、存在しないページへのリクエストのみ共通の404 Not Foundページを表示したいという場合には/routes/+error.svelteを設置するだけで共通の404 Not Foundページが出力できる。

しかし、SSG(Static Site Generator)においては、カスタマイズされた404 Not Foundページを表示したい場合に、ホスティングサービスにあわせたエラー用の静的なHTMLを設置する必要があり、冒頭で例に挙げたCloudflare Pagesの場合には404.htmlというファイルが必要になる。

ここまでを踏まえて、/routes/+error.svelteをビルドディレクトリに任意のファイル名(今回の例では404.html)で出力する方法が公式に提供されているのでは?と思い公式ドキュメント(主にadapter-staticに関する情報)を見たが、はっきりとマッチする情報が見つからない。。

ということでSvelteKitのGitHubリポジトリのIssueを探してみると、まさに全く同じことを実現する方法について、質問が出ていた。

このIssueは結局こちらのIssueに引き継がれることとなったのだが、最終的にコントリビューターの方のコメントとともに既に適切な機能提供がされているという理由でクローズされている。

しかし、実際に提示されている方法を試してみたところ当初の質問に対する回答、機能提供としては少し不足がある気がする。

というのも最終的にadapter-staticfallbackオプションで出力したいエラーページ(404.html)を指定し、prerendertrueにするという方法が提示されているのだが、このコメントの通りこの方法は/routes/+error.svelteを404.htmlとして出力するわけではなく、404.htmlを空ページで出力しているだけに見受けられる。

また、ConfigurationerrorTemplateなど色々と試してみたが、adapter-staticfallbackに指定したページをカスタマイズする方法がどこにも見当たらない。
※ここは私の調査が不足している可能性もあるのでご存じの方がいましたらコメントいただければと

ということで一旦、公式に提供されている機能での実現を諦め、Issueで他の方がコメントしているやり方をベースに独自の実装方法で対応することとした。

対応

まず、シンプルにビルドディレクトリに/404.htmlが出力されれば良いだけなので、直接/routes/404/+page.svelteを実装すれば解決では?と考えた。

注意
trailingSlashalwaysだと、/404.htmlではなく、/404/index.htmlが出力されてしまうが、Cloudflare PagesではRoute matchingがこのような仕様のためtrailingSlashneverという前提のもとの対応。

実際、この方法でビルドしてみると/routes/404/+page.svelteの内容が/404.htmlとして出力できた。

また、$ vite devで稼働する開発環境では引き続き/routes/+error.svelteが404 Not Foundページになるが、別ファイルで同じレイアウトを管理するのは冗長なので、/routes/404/+page.svelte/routes/+error.svelteをレンダリングするような実装としておくことで一つのページで管理することができる。

/routes/404/+page.svelte
<script lang="ts">
  import ErrorPage from '$routes/+error.svelte'
</script>

<ErrorPage />

まとめ

今回の実装例は公式ドキュメントで提示されている方法ではなく少しハック感が強いため、今だに「適切な方法が提供されているのでは?」と思っているのでご存じの方がいましたらコメントいただけますと幸いです。

参考

6
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?