すしのへや

thumbnail of tech/chofusai-2023-website

第73回調布祭Webサイトを​支えた​技術

各方​面に​感謝を​込めて
17 min to read

この記事はUEC Advent Calendar 2023の1日目の記事です。

こんにちは、 すしです。 大学では調布祭実行委員会バーチャルライブ研究会で技術面のサポートをしています。

つい先日、2023年11月24日から26日にかけて開催された、電気通信大学の大学祭「第73回調布祭」において、 Webサイト制作という形で運営に参加させていただきました。

自分が担当した分野での振り返りや技術的メリット・デメリットなどを書き残しておきたいので、1 当初の予定トピックを変更してこの記事を書くことにしました。

ということで、カレンダー1日目からマニアックな記事になってしまいますが、よろしくお願いします。

完成した第73回調布祭公式Webサイト

はじめに

私は主に

  • 技術選定・初期実装(後述する内製Markdownライブラリなど)
  • メンバーの進捗の統合・修正
  • パフォーマンスやアクセシビリティの向上
  • デプロイ・インフラの構築

を担当しました。

大変好評だった学内マップや、企画一覧ページの検索機能は主にいーちゃん(@e_chan1007_u)がゴリゴリ実装してくれました。 今の私では絶対力が足りません。偉業すぎる。改めて感謝の意を表します。

使用した技術とインフラ

主に使用した技術やインフラは以下の通りです。

ということで、それを選んだ理由や、メリット・デメリットなどをつらつら書いていきます。

Next.js(App Router)

実はもともとNext.jsを使うこと自体は決まっていました。 というのも、2023年度新歓サイトを制作する際にNext.js(Pages Router)を使っており、 できればそこから大きな変更を加えたくなかったからです。 未経験者もしくは初心者が多かったこともあり、インターネット上の情報が多くReactの充実したエコシステムが享受できる点でもNext.jsはある程度合理的な選択肢になります。

ということで、特に何もなければPages Routerを使うはずでしたが、本格的に環境構築や制作の準備を始める直前にビッグニュースが飛び込んできました。

App Router Stable?!?!?!?!?!

App Routerのメリット

私はもともと、Pages RouterにはNext.js独特のコードがかなり多く、一般的なhtmlと同じ構造で書けるApp Routerの方が下の代へ引き継いでいくのに適していると考えていました。

今フロントエンド全体を見てもhtml標準、WebAPI標準に回帰していく動きがあり、App RouterはPages Routerと比較した際により将来性のある選択肢として考えられます。

追記(2024.03.03):
当時はそう感じていましたが、現状App Routerがやや未成熟であることからPages Routerも十分に使われていますし、私は今後もPages Routerは有力な選択肢だと考えています。

また、Nested Layoutやloading.tsxを用いたローディング表示、MetaDataAPIopengraph-image.tsxによる動的なメタデータ生成など、 全体的にフレームワーク側の手厚いサポートがあり、これらを上手く使っていくことで精鋭揃いでないチームでもある程度Webサイトの速度や品質を担保していけると考えました。

以上の理由から、安定版になったばかりではありますが、より直感的で将来的にも読みやすそうなApp Routerを採用することにしました。

App Routerのデメリット

とはいえメリットばかりでないのも事実で、当然デメリットも感じました。

App Routerでは、React Server Componentと呼ばれる概念がデフォルトになっています。 よって、何も設定しなければサーバー上でレンダリングされて、ブラウザには最終的なHTMLが渡されます。

このため、useEffect()のようなブラウザ側でしか動かないコードを使う場合は明示的に分割する必要があり、 状態管理も今までとは大きく異なるため複雑な操作を伴うUIなどはほぼApp Router化の恩恵を感じませんでした。

また、ある程度フレームワークの意向に沿った形でコードを書いていくことになるので、普段は使わない脳を使うように感じます。 全体的にフレームワーク独自要素が多いため、ドキュメントをきっちり読んで上手く付き合わないと難しい部分があります。

追記(2024.03.03):
さらに、不安定な挙動やハイペースな変更、キャッシュ制御の難しさなど、複雑なWebアプリケーションなどを作る際にはさらなる苦しみがあると感じています。

Markdown

なんでMarkdown…?と思われた方もいるかもしれませんが、実は今回、一部ページコンテンツと企画データの管理にMarkdownが使用されています。

例えばこのページで使われています。

このページの実態は独立したMarkdownファイルであり、それを内製ライブラリを使って

  1. /news以下のページを生成する際に指定したディレクトリ以下のMarkdownを探索する
  2. ファイル名に対応するパスを振り分ける

のような手順を踏むことで擬似的なファイルベースルーティングを実現しています。 また、この際Markdownのフロントマターに必要な情報も書くことで、効率よくページを生成できるようにしています。 企画データの管理も同様の方法で行いました。かなり楽で良かった。

ちなみにこのライブラリを試験実装したのが旧個人サイト内のブログだったりします。2

Cloudflare

いわずと知れたつよつよCDN+αですね。私が導入を推し進めました。 CDNというのはContent Delivery Networkの略で、コンテンツをユーザーから近い場所にキャッシュして配信する仕組みのことです。

実際にした設定は多数あるため割愛しますが、複数の最適化により75%のアクセスをCDNで処理できました。 また、当然CDNからのレスポンスはVercel上のNext.jsサーバーからのものより速く、パフォーマンスの向上に繋がりました。

Cloudflareの帯域幅分析。総トラフィック約30GBのうち22.5GBをCDN上のキャッシュでさばいている。 オリジンへ飛ぶ帯域幅を22.5GB削減できました。

また、過去の調布祭ページなどを記録用として静的ホスティングするのにCloudflare Pagesを使用しています。第73回サイトもいずれこちらに移行する予定です。

追記(2024.03.03):
現時点でCloudflare Pagesへの移行は終わっていますが、Next.jsは本来Cloudflare Pagesで動かすものではないのでOGP画像生成などで不具合が出ています。

Vercel

まあNext.jsを使うならVercelでしょう。特に深い意味はないです。

…というのは嘘で、実は当初はCloudflare Pagesにデプロイする予定でした。 というのもVercelは無料枠での帯域幅に月間100GBという制限があるのに対し、Cloudflare Pagesは事実上無制限だったからです。

ただ、どうしても当時Cloudflare Pagesのようなエッジ上でNext.jsを手軽に動かす方法はありませんでした。 その上、仮にデプロイしたとしてもすべての機能が使える保証もありません。 これらの点や、調布祭サイトで最も帯域幅を抑える効果が大きいのは画像などの静的アセットの最適化であるという判断から、安定を取ってデプロイ先をVercelに変更しました。

使用可能な帯域幅に上限がある分より帯域幅の観点での最適化に力を入れ、結果的には無料枠のわずか7%の帯域幅に抑えることができました。

特に意識したこと

調布祭サイトは、当然ながら開催期間中はアクセスが集中します。今年度は本格的にコロナ禍前の姿に戻すということで入場予約も不要になり、アクセス数の予測ができない状態でした。 さらに、もともと学内の電波状況がいいとは言えない状態なため、通信速度がある程度落ちた状態でも高速に読み込める必要がありました。

このため、可能な限りユーザーに近いCDNまででリクエストを完結させて、また配信されるコンテンツのサイズを小さくする工夫をしました。

これにおいて最も重要なのが画像の最適化です。 Next.jsでは<Image />コンポーネントに画像サイズを事前に指定することで、画面幅に合わせて最適な画像を配信してくれます。

これをきっちりやる前とやる後では、明らかに使用される帯域幅に変化があるくらい効果的でした。

また、Google AnalyticsはCloudflare Zarazを経由して使用しました。 Cloudflare Zarazは、CloudflareのCDNを通過する際にHTMLを書き換えて追加コードを挿入できる機能で、 これを用いてCDN上でGoogle Analyticsのコードを追加しています。 こうすると、余分なサードパーティへのリクエストがなくなるので、パフォーマンスの向上に繋がります。 まあこれは私が使いたかっただけなのですが…

他にも遅延レンダリングや一部アセットのprefetch、 重たいコンポーネントの動的読み込みやスケルトン表示を行い、高速かつUXを損なわない表示が実現できました。 Webサイトの動作の軽さについての声も少し耳にしたので嬉しかったです。

うまくできなかったこと

当初はデザインをFigmaなどで組み立ててから実装する予定でした。 しかし、肝心のWebデザイン経験のある人間がほとんどいなかったためデザインが決まらないまま時間が経ち、 ぎりぎりになってからその場の勢いで実装するという形になってしまいました。 このため、かなり簡素なデザインになってしまい、他の大学祭のサイトと比較してもあまりお祭り感のないものになりました。 これは本当に悔しくて、お褒めの言葉を頂いていても「もっとワクワクするデザインにできたはずなのに」という気持ちがずっとあります。

また、7割以上の人員が2023年3月以降に初めてHTMLを触った、という初心者だったにも関わらず、 十分な講習時間を取れないまま実装を進めてしまいました。 このため、予想以上の手戻りや遅れが発生し、調布祭2日目の昼頃にようやく実装が完了するという結果になってしまいました。

限界作業をやめよう!その1
限界作業をやめよう!その2

これから、委員会内ではこれらを来年度どのように改善するかを考えていきます。

おわりに

長くなってしまいましたが、第73回調布祭Webサイトの裏側を話せる範囲で書いてみました。 この制作は、ほとんどの人員がWeb未経験の状態から数ヶ月で比較的大きなサイトを作るという、私にとって、そして調布祭実行委員会にとって大きな挑戦でした。 私自身この制作を通して学んだことが非常に多く、春先は新歓サイトの作成で手一杯だったのが今では個人でもWeb制作を行えるようになりました。

たくさんの方にご迷惑をおかけし、また、たくさんの方にご協力いただきました。 最終的に至らぬ点はあったとはいえ、多くの方に好評をいただけたことは本当に嬉しかったです。 記事内では書ききれなかった調布祭実行委員会編集局のメンバーの偉業、および委員会員やOBの方々、また協力してくださったすべての方々に感謝申し上げます。

さて、 明日の記事はローネさんの「入力デバイスとして1年間板タブを使い続けた話」です。 マウスの代わりに板タブ使ってるってことだとしたら怖すぎる、楽しみですね。

それではまたどこかで。

脚注
  1. 疲れており完全に新しい内容で記事を書く気力がないです。悲しいね。

  2. 急に旧個人サイトをNext.js(App Router)で作ったのは調布祭の準備の一環でした。