diary

I like Hatena Star with a text selection.

2025-12-04

elin.pocke.me

Elinキャラクタービューワーを色々いじっていた。

Elin は EA と Nightly という2本のブランチが走っているのだけど、今まではキャラクタービューワーではEAにしか対応していなかった。それをNightlyに対応するようにしたのが一番大きな変更。

これを実装するにあたって、今までCloudflare Pagesでホスティングしていたのを、Vercelに載せ替えた。 なぜそんなことをする必要があったかというと、Cloudflare Pagesのファイル数制限に引っかかったため。

Cloudflare Pagesは静的Webアプリをホスティングするためのプラットフォームなのだけど、1つのアプリに対して20,000ファイルしかファイルを置くことができない制約がある。 20,000ファイルというと結構寛大な制限に見えるのだけど、キャラクタービューワーが使っているNext.jsでは1つのhtmlに対してたくさんのメタファイルを生成する。

$ ls out/ja/EA/charas/adv_ivory/
'__next.$d$lang.$d$version.charas.$d$id.__PAGE__.txt'  '__next.$d$lang.$d$version.txt'   __next._head.txt    index.html
'__next.$d$lang.$d$version.charas.$d$id.txt'           '__next.$d$lang.txt'              __next._index.txt   index.txt
'__next.$d$lang.$d$version.charas.txt'                  __next._full.txt                 __next._tree.txt

今まではそれでもなんとかなっていたのだけど、EAとNightlyの2本に対応したことでファイル数が約2倍になり、この制限を超えてしまった。HTMLのページ数自体は2800件程度でまだまだ余裕があるのだけどねえ。

これを回避するために、最初はCloudflare Workersへの移行を試した。同じCloudflareのサービスだけど、Workersの方はNext.jsのサーバープロセスをホスティングしてくれる。こちらだとファイル数制限がないので(静的Webアプリではなくなるものの)動くのではないかと思って試してみた。 10万req/day まで無料であり、現状のリクエスト数が直近30日で平均3770req/dayなのでしばらくは無料でいけるだろうとの見込み。

これも実際にデプロイする直前まではいけたのだけど、デプロイログを見るとエラーが出ていた。どうやらCloudflare Workersの無料枠だと、1つのアプリは圧縮後で3MB以下に抑える必要があるが、それを超えていた。正確な数値は覚えていないけれど3~4MBだったと思う。

SSGするページ数を減らせばなんとかなるかなあと考えたりしていたのだけど、試しに最小限のデータでビルドしてみても(多少減ったものの)3MBを超えていて、どうやらNext.jsなどのライブラリ自体のコードがそもそもデカくて厳しそうだった。

ということでCloudflareは諦めて、別サービスでホスティングすることにした。どうやらVercelはこれらの制約がない(or 現実的なゆるさ)ようなので、Vercelに移し替えることにした。基本的にSSGをメインで動かしているので、コードの変更はほとんどなかった。Cloudflare Workers移行のために昨日のうちにDNSTTLを小さくしておいて正解だった。

Cloudflare Pages / Workers はNext.jsをホスティングするのに向いていないのでは……という気持ちになっている。まあSSGしているページ数が多すぎるのが問題とも言える。

Nightly対応の実装自体は昨日のうちに終わっていたのだけど、デプロイで手間取って今日1日かかってしまった。 実装もまあまあ大変で、今まで必要なかったバージョン情報をアプリケーション内で全体的に引き回す必要があって、大きな変更になった。ただ面倒なことは全部Claude Codeさんがやってくれたので、気分的には割と楽だった。

ここ数日はゲームをやっている時間よりもゲームのためにコードを書いている時間のほうが長い。