ZEN大学のWebシラバスを支える技術

本記事は ドワンゴ Advent Calendar 2024 の25日目の記事です🎄

はじめに

こんにちは。Webフロントエンドチームの山口です。

この度、鋭意開発しておりました、ZEN大学のWebシラバスを公開しました(以降シラバスと表記)。

公開後、多くのポジティブなご反応を頂いており、大変嬉しい限りです。

さて、本記事ではシラバスの技術面に焦点を当て、全体のアーキテクチャとWebフロントエンドの技術構成についてご紹介します。ぜひお付き合いください。

シラバスについて

syllabus.zen.ac.jp

2025年4月開学の「ZEN大学」の履修科目の概要や科目情報を、誰でも簡単に検索・閲覧できるWebサイトです。 在学生や大学関係者への情報提供はもちろん、入学を検討している学生やその保護者に向けて、ZEN大学の魅力を伝える広報的な役割も担っています。

履修パターンや分野などの多様な条件で科目を検索できるため、自分に合った科目を簡単に見つけることができます。 また、新たな科目との出会いを促す機能として、各科目にはタグや関連科目が設定されています。これにより、履修選択の幅が広がり、個々の目標に合った履修計画を立てやすくなっています。より詳しくは、ぜひお手元でご覧になってみてください。

アーキテクチャ

上図をご覧ください。順を追ってご説明します。

まず、大学の入稿担当者が、Jenkinsの入稿ジョブを通じてシラバス用の入稿データをS3に保存します。入稿データには2種類あり、テキストデータ(CSV)と画像データが存在します。

入稿後、Transformerと呼ばれるデータ変換層によって、入稿データをWebに適したフォーマットへと変換します。(CSV → JSON, 画像 → WebP)。*1

そして、変換後の入稿データをもとにアプリケーションをビルドし、成果物(HTML, CSS, JS, etc...)をS3へ保存、CloudFrontを通じて配信し、最終的にシラバスがWebブラウザ上に表示されます。

そのほか、科目の検索機能のために、検索用のAPIを別途立てています。

検索時はHTTPリクエストをAPIへ送信し、APIはS3上の入稿データ(JSON)をデータソースとして、検索結果を返す構成となっています。

技術構成

Next.js(App Router)

nextjs.org

前提として、シラバスには以下の特性があります。

  • 静的コンテンツが主。科目の検索機能など、一部に動的コンテンツも存在する
  • データ(科目, 教員, タグ, etc...)の更新頻度は低く、ユーザー固有のデータもないため、必要なデータはビルド時点でわかっている
  • SEOとパフォーマンスが大事

これらの特性を踏まえ、シラバスではレンダリング手法としてSG(Static Generation)を選択し、その手段として Next.js(App Router)を採用しています。

静的コンテンツは Server Components、動的コンテンツは Client Components としてビルド時にプリレンダリングStatic Exports で静的アセットを出力し、S3に保存、CloudFrontから配信しています。

Panda CSS

panda-css.com

Next.js(App Router)では、CSS Modules、Tailwind CSS、CSS in JS など、多様なスタイリング手段をサポートしていますが、シラバスでは Zero Runtime CSS in JS である Panda CSS を採用しています。

Server Components / Client Components をサポートしていることはもちろん、デザイントークンレスポンシブデザイン をデフォルトでサポートしています。

シラバスでは、カラー、タイポグラフィ、スペーシングなど、デザイントークンを定義しており、デザイントークンベースでUIコンポーネントを開発しています。加えて、レスポンシブデザインの要求もあることから、それらが簡単かつ便利に扱える点は魅力でした。

また、教育事業のWebフロントエンドチームでは CSS in JS の採用が多く、扱いに慣れているメンバーも多いことから、Tailwind CSS などと比較して、キャッチアップコストを抑える目的もあります。

そのほか vanilla-extract なども候補にありましたが、Server Components のサポートに関して、当時 Issue(*2)が報告されていたことなどを含め、採用を見送っています。

今回は Delivery(納期)が重要なプロジェクトであることを踏まえ、極力リスクや開発コストを抑える方向の判断をしていますが、そうでなければ別の選択もあり得たかもしれません。

Radix UI(Primitives)

www.radix-ui.com

シラバスでは独自のデザイン要件があることから、スタイルを含まない、いわゆるヘッドレスなUIライブラリを選択しています。UIライブラリにスタイルが含まれている場合、スタイルの上書きやカスタマイズが必要になり、その分の手間と複雑さが発生することを避けるためです。

また、アクセシビリティに正しく配慮したコンポーネントを一から自前で開発するのは大変なため、最低ラインはライブラリに頼りたい...といった動機もあります。

2024年6月のリリースでは、Radix UI(Primitives)の全コンポーネントがRSC互換となりました。

そのほか、提供されているコンポーネントの数と種類、コンポーネント単位で必要なものだけを導入できる点などを含めて検討し、Radix UI(Primitives)を採用しています。

GitHub Actions

github.com

基本的なCI/CDの用途はもちろんですが、そのほか、GitHub Pages と組み合わせ、PRごとに独立した動作確認環境を立てる仕組み(ワークフロー)を構築しています。

PRの作成時、またはブランチに変更が加えられたタイミングでワーフクローをトリガーし、ブランチの内容をもとにアプリケーションとStorybookをビルド、成果物をGitHub Pagesにデプロイし、それぞれのURLをPRにコメントとして通知する仕組みです。

URLにはPR番号を含めており、PRごとに独立した環境となっています。最終的にPRをクローズしたタイミングで環境を破棄しています。

PRのレビュー時などにローカルで環境を立ち上げる手間が省けるほか、ローカルに閉じていない環境であるため、URLをデザイナーなどの他チームに共有し、開発中の機能やコンポーネントを確認してもらうといった使い方をしています。

その他

あまり特筆する点がないものについては、簡単に列挙する程度に留めます。

おわりに

さて、ZEN大学のWebシラバスを支える技術と題して、全体のアーキテクチャとWebフロントエンドの技術構成についてご紹介しました。

プロダクトやチームの特性、その時々の状況などにより、適した技術は異なるものですが、少しでもご参考になる部分がありましたら幸いです。

本記事では、バックエンド領域について深く触れませんでしたが、データ変換層(Transformer)に関する記事を過去に公開しています。もしご興味あればご覧ください。

blog.nnn.dev

We are Hiring

株式会社ドワンゴの教育事業では、一緒に未来の当たり前の教育をつくるメンバーを募集しています。カジュアル面談も行っています。お気軽にご連絡ください!

カジュアル面談応募フォームはこちら

www.nnn.ed.nico

開発チームの取り組み、教育事業の今後については、他の記事や採用資料をご覧ください。

speakerdeck.com

*1:シラバスでは画像を多用していることから、WebPを使用してサイズを軽量化する。遅延読み込み(Lazy Loading)を活用するなどの最適化をしています。なお、Next.jsでは、画像最適化の機能を備えた next/image が提供されています。ただし Static Exports 環境下では、そのまま next/image の最適化機能を使用することはできません。この場合、custom image loader を定義する、next/image ではなく自前で最適化するなどの選択肢があります。Next.jsのリポジトリ上でも議論されていますので、ご興味あればご覧になってみてください。

*2:https://github.com/vanilla-extract-css/vanilla-extract/issues/929