きっかけ
ここ数年、IoTのデバイスやアプリを作ったりfont作ったりしていたけども、まともにドメイン取ってサーバー構築してちゃんとしたサイト・サービスを運用していくという『webのいろは』的なことをやっていませんでした。
とは言え、個人で作るものの大半はgithubpages + gasで作ったサーバーレスなAPIでどうにかなるようなもので大半だし、既に個人で複数ドメインを持って自宅サーバーも稼働している中「いろは」を使う場面が減ったのもあります。
そんな中、昨年末にとあるきかっけから、久々にドメインを取得してFigma Designのプラグインランキングサイト(pexr.net)を開発するに至りました。
技術的課題を設ける
元々のページがSSRじゃないのでwgetやcurl経由でDLしても必要な情報が取得できないとか色々あるんですが、せっかくのチャンスなので『今までやったことないことに挑戦しないとなぁ』と思いながら漠然と考えていた時、『あ、一切のサーバーサイド言語を使わず、静的ページを生成してGithub Pagesを使えばサーバー代がタダで済むじゃん』と思いました。(なんちゃってJAMStackと呼んでいました。)
実務としてはガラケーサイトが全盛の頃、各キャリア向けのコンバーターを作ったり、既にあるdocomoの大量なHTMLをwillcom用に変換するツールを開発した経験あるのでチャレンジングか?と言われれば微妙(当時のガラケーはJavascriptが動かないのでJがない AMStack? )なんですけども。
で、手元にあるラズパイをbuildサーバーにして色々スクレイピングのプログラムを書いてsqliteにデータを突っ込んでhtml生成プログラムを書いてgithubにpushする感じで構築しました。
まぁ、Github Pagesを使う時点でCDNに乗っけてないのでJAMStackの特徴の1つの『高速化』の部分を切り捨てることにはなるんですけども(とは言え、サーバーサイドのアプリケーションから生成してキャッシュに乗っけるより初回は多少早いはず)、SSLありのサイトを手軽にポンってできるのは大きいなぁと思っていました。
無料の Github Pagesじゃぁ細かいところに手が届かない

これが、業務であればCIツール用のマシンが24/365稼働していたりするのでいいんでしょうけど、大掃除の際に電源抜けちゃうとかSDカードの寿命が来ちゃうとか色々考えると心許ないのが正直なところです。
『とりあえず、ドメインだけでも取って、Github PagesをDNS設定すればいいかなぁ』とは思っていたもののLet's Encryptの設定とか考えると段々面倒になりNoteの記事を書いている間に心の中では『もうドメインと取って、サーバー借りてお金を出してやろう』と決めてました。
本当にオートスケール、CDNが必要か?
さて、個人が運営するサイト・サービスにおいてオートスケールやCDNを使う必要があるのか?と言うとどう考えても自分のサイトはそこまでのアクセス数が見込めるようなものではありません。
むしろ、思いつきで作っているので下手にCDNに載せるとデザインの変更の度にキャッシュを消して…ってのを繰り返すのが目に見えてますし、よくある『10万人のMAUを考えてたのに結局関係者しか使わないDAU1,000以下…』みたいになるので月1,000円以下のVPSでサクッと構築しました。
buildサーバーとして使っていたラズパイのプログラムもVPSに同居させ『nginxで静的ページをただ出すだけ』って感じの構成にしました。この時点でJAMStackではなくなってますけどもね…
(もちろん、スクレイピングでCPUやメモリ、転送量がどのくらい使うのか?も確認して他のサーバーに迷惑かけないようなプランを選択しています。)
利点?
JAMStackでよく言われる利点として
- サーバーで生成しないので高速(CDN使うともっと高速)
- 静的サイトなのでセキュリティ的に安心
- スケーリングが楽
- 開発者が楽
(https://jamstack.org/why-jamstack/より意訳)
って感じのことが挙げられてますが、高速って言いながら結局JSのフレームワークやCSSをBEMで表記するってのはちょっとした矛盾を感じたりしたのでJSフレームワークなし、BEM表記なしにしています。
また、静的サイトだからxssやSQLインジェクションに強いものの、別にsshやApacheやnginxのwebアプリケーションの設定によってはそもそもな話で(log4jの脆弱性でも盛り上がっていた時期でしたし)有名なフレームワークはその辺を考慮されて作られているので『言うほど?』って感じです。
スケーリングに関してはそこまでのコンテンツじゃないので却下、ただ開発者が楽?という点は『楽には全くならない』と思いました。
開発者が楽(Better Developer Experience)とは?
まず、ここでの『開発者』って主語が微妙だなぁと。
確かにサーバーにRDBMSやKVSを置かなくてよくなることでサーバーサイドエンジニアはいらないように感じますが、実際静的HTMLを生成するbuildサーバーではDBやKVSを参照することが多いように感じています。
そして、一番面倒なのは、サーバーサイド言語で常套句?とも言えるincludeなどが使えないので、例えばドメイン移管などでサイトのフッターのURLが変わると今まではfooter.phpみたいなファイル1つを更新してサーバーにdeployすればよかったものが下手すると1,000ページ以上、生成し直しになります。
実際、自分もサイトをちょこっと変えるのに毎回全ページ生成し直しのバッチを叩いて『うーん。これってなんだろう』って感情が湧いたのは正直なところです。(例えばlsコマンドやfindで特定の日時で変更されたファイルを探すってのがやりにくいとかいう弊害もあるなぁと)
で、今までのやり方だと、超絶緊急性の高い場合サーバーエンジニアがsshで入ってfindとsedを使って一括置換やTOPページだけサーバー上で変更みたいなことも経験上あったんですが(本来はソース管理ツールから必ずdeployが正しいですけども)この辺りもbuildの仕組みを知ってるエンジニアが都度プログラムを変更しなきゃいけないとなると、そこまでBetterかなぁ?と感じました。
年末年始にありがちなスクリプトで時限式にheaderのバナー1個の変更のためにcronもしくはatコマンドでjobを作ってbuildサーバー+scp的な何かが動くことになるわけですよね…
また、少なくともユーザーが見ているページが素のHTMLだからプログラムに疎い人が運用・運営任せられるか?と言われると疑問符が浮かびました。(ここは別にJAMStackに関係なくJSのフレームワークやSCSSとか使う時点でできない人はできないですが一括置換コマンドとか叩ける人って意外と少ない印象があります。)
静的サイトで失われたもの
今回一番課題に感じたのは、titleやogpの日付部分のi18nでした。
今回のサイトの都合上UXの向上としてop:imageにどの日付で集計したか?を記載したpngを生成していますが、現状のHTMLの仕様でog:imageは多言語化対応できないのでクライアント側の言語を取得して動的に変更すべきだと思いました。
無駄だろうなぁと思ってJSで書き換えを行ったりしましたが案の定意味がなく、こうなるとphpなどのサーバーサイドアプリケーションでhead側を動的に出した方が圧倒的にUXは向上します。
一応解決する1つの手段としてはURLを「/en」「/ja」とかで分けていくってのもありますけど、流石に日時表記事にディレクトリ切るぐらいならサーバーサイドで解決すべきな気がします。
そうじゃなくてもSNSでシェアした場合og:imageは国際化対応できません。
まぁ、bodyから下はunixtimeを元にJSで対応したんですが、こういう部分を考えるとサーバーサイドあり気で作った方がよかったなぁと思っていますが、ただその部分以外は確かにJAMStackで問題ないのも事実で正直答えは出ていません。
↑日本語でアクセスした時、↓英語(アメリカ)でアクセスした時
最終的に暫定対応としてアメリカ圏の記述とYYYY/MM/DDを併記することで暫定対応しましたが、根本的な解決としてはHTMLの仕様変わって対応できるようになる気がするのでその時を待ちます。
まとめ
久々にサイトを作りましたが、favicon作る面倒さ、レスポンシブ対応、DNS、nginxの設定、マークアップとか面倒臭さ満載でした。
その中でも、op:imageの件は脳内では想定していなかった問題だったので、適当なテストではなくある程度のクオリティのものをちゃんと作ることで分かることがありました。
今回のサイトはJAMStackには向いてなかったのが一番の敗因(?何に負けたのか不明ですが)ですが、マイノリティの日本語圏に住みi18nが当たり前となりつつあるwebの世界でサーバーサイドの言語を使わず静的ページで対応できるパターンがちゃんと分かってないと痛い目に合うなぁと改めて思いました。
多分、どこかのタイミングでphp入れるだろうなぁという予感を残してしばらくこのまま運用していきます。