2022/02/12追記。
この記事は、sveltekitをgithub pagesに置いたとき、いくつか回避策を講じなければ動かなかったため記述したものですが、その後、sveltekitの更新に伴い、ほとんどの躓く箇所はなくなりました。
*) 特に、Handling of static assets with paths.baseが修正されたため
そのため、以下に書いてあることはほとんど役に立ちません。
↓を参照すれば、GitHub Pagesにデプロイする際の注意点がまとまってます。
https://github.com/sveltejs/kit/tree/master/packages/adapter-static#github-pages
昔の話です
フロントエンドに入門したいと思い、最近良く耳にするSvelteKitで、もともとGitHub Pagesに置いていたサイトを作り直しました。
作り直したのは、Center Pin(g)というサイト、で、任天堂のゲーム、ポケモンユナイトの大会結果を収集し、プレイヤー別に見れるようにしているものです。レポジトリはここです。
もともとは静的サイトとして作っており、プレイヤーのリスト1ページと、プレイヤー7,000人弱のhtmlを事前に生成してpushしていたのですが、リストページが縦に長過ぎて使用に耐えない感じになったため、ページングを導入したいのもあり、Svelteを利用して置き換えました。
置き換え後も静的に生成してる点は変わりなく、プレイヤーに関しては、リスト表示とプレイヤーの詳細表示に、2つのhtml、プレイヤーリストのjsonが一つ、7,000弱のプレイヤー別jsonを生成しています。
SvelteKit
SvelteKitに関しては、公式サイトと、公式ドキュメントを参考にしました。
GitHub Pagesへのデプロイ
SvelteKitは可能であれば事前にhtmlを生成(prerender)します。そのサイトに用意されているページがすべてprerender可能である場合、静的なサイトとして、例えばGitHub Pagesにデプロイできます、と、Static sitesに書いてあります。
ここでは、adapter名の変更のみに触れていますが、他にも最低二点変更しないと動きませんでした。
svelte.config.jsを変更する
1つ目はadapterのsvelte.config.jsのパスに関する設定です。GitHub Pagesはユーザー単位のもの、自分で言えば、https://k2da.github.io/ と、プロジェクト単位のもの、今回で言えば、https://k2da.github.io/center_pin_g/ のようなURLがあります。
ドメイン直下でない場合は、パスを補正するために、kit pathsのbaseを指定する必要があります。なので、svelte.config.jsは以下のようにしました。
const config = {
preprocess: preprocess(),
kit: {
adapter: adapter(),
target: '#svelte',
appDir: 'app',
paths: { base: '/center_pin_g' },
serviceWorker: { register: false }
},
};
serviceWorkerは使うつもりがなかったのと、なんかエラーが出るのでregister: falseにしてあります。
.nojekyllファイルを作成する
svelteはデフォルトでは、_appというディレクトリにビルドされたjsファイルを置きます。上のsvelte.config.jsではこれを appという名前に変えていますが、これは、GitHub Pagesがデフォルトでは_から始まるファイルやディレクトリを見えなくする設定だからです。
しかし、svelteでは__layout.svelteなど、他にも_で始まるファイル名を使用する必要があります。GitHub Pagesでは、.nojekyllというファイルが存在している場合は、_からはじまるファイルでも表示してくれるようになるので、こちらをGitHub Pages用のレポジトリの直下に置いておきます。
デプロイするファイル
↑のようなsvelte.config.jsでyarn buildすると、以下のようなディレクトリが生成されます。
build
├── Header
│ └── index.html
├── app
│ ├── assets
│ ├── chunks
│ ├── error.svelte-07d53cda.js
│ ├── manifest.json
│ ├── pages
│ │ ├── Header.svelte-868c8319.js
│ │ ├── __layout.svelte-65f3d841.js
│ │ ├── index.svelte-844a9124.js
│ │ ├── player
│ │ │ ├── Pager.svelte-3b89f99f.js
│ │ │ ├── __layout.svelte-83833026.js
│ │ │ ├── detail
│ │ │ │ └── index.svelte-e2caccc3.js
│ │ │ └── index.svelte-4cbd7611.js
│ │ └── tournament
│ │ ├── detail
│ │ │ └── index.svelte-21fb8c36.js
│ │ └── index.svelte-31b84eca.js
│ └── start-c82f3262.js
├── center_pin_g
│ ├── app
│ │ ├── assets
│ │ ├── chunks
│ │ ├── error.svelte-2620f990.js
│ │ ├── layout.svelte-304898be.js
│ │ ├── manifest.json
│ │ ├── pages
│ │ │ └── player
│ │ │ └── index.svelte-3662c30c.js
│ │ └── start-d62ca2b8.js
│ ├── player
│ │ ├── 25a2631193acf5c9293e5294ca532b65f4faadff.json
│ │ └── players.json
│ └── tournament
│ └── unite_online_2b.json
├── index.html
├── player
│ ├── Pager
│ │ └── index.html
│ ├── detail
│ │ └── index.html
│ └── index.html
└── tournament
├── detail
│ └── index.html
└── index.html
なぜかappが2つあります。正直なぜ二個できるのか理解できていないのですが、center_pin_g のサブディレクトリにあるところを見ると、pathsの設定が関係していそうです。また、center_pin_g には、staticに含まれていたファイルもコピーされています。
今回のサイトでは、staticに含まれていたjsonファイルは別途生成しているので、center_pin_gのファイルはすべてコピーしていません。それでも動いているようなのでいまのところ、2つめのappディレクトリが、なににつかうファイルなのかはよくわかっていません。
ローカルでの確認
SvekteKitでは、yarn devでローカルでサーバーを起動して便利に開発を進めることができます。しかし、この状態では本来GitHub Pagesにデプロイする際は使えない、EndPointsが使えてしまうし、静的サイトとして使える場合でも微妙に挙動が異なる場合があります。
たとえば、開発用サーバーで、http://localhost:3000/center_pin_g/player にアクセスした場合、このURLのままでアクセスできます。しかし、GitHub Pagesで、https://k2da.github.io/center_pin_g/player にアクセスすると、https://k2da.github.io/center_pin_g/player/ と最後にスラッシュが入ります。これは、player.svelteをビルドする際に、実際には、player/index.htmlとしてビルドするためです。
自分は一度これで混乱したため、最初から全てplayer/index.svelteのような形で実装しました。
先程の、ビルドされたファイルを実際にデプロイする際の位置関係など、ローカルでもGitHub Pagesに近い挙動で確認したいケースが出てくると思います。ファイルを返すだけのWebサーバーでいいので、なにを使っても可能ですが、自分はbasic-http-serverを利用しています。これは、ルートにしたいディレクトリへcdして起動するだけで、port 4000にwebサーバーを立ててくれるので、yarn build -> ファイルを動かす -> basic-http-serverすることで、GitHub Pagesに近い感じで確認できます。
感想
ReactやVue、next、nuxt等を全然知らないのでどうせなら新しい感じのものを触ってみるかと思いSvelteを選びましたが、非常に書きやすく手軽だったのでおすすめです。
Cloudflare Pagesや、Netlifyにデプロイするのであれば、サーバー側の処理もEndPointsとして記述できるようなのでそのうち試したい。