コミックフェスタのフロントエンドをRailsからNext.jsにページ単位で移行しています
株式会社ウェイブでComicFestaのエンジニアリングマネージャー・開発エンジニアをしている多田です。
今回の記事は、コミックフェスタのフロントエンドをRailsからNext.jsにページ(URL)単位で移行するプロジェクトが進行中なので、それに関する話を書こうと思います。
背景
コミックフェスタはリリースから現在までおよそ13年が経つ、モノリシックなRuby on Railsアプリケーションです。長い年月の間に様々な改修を繰り返すうちに、フロントエンド周辺は以下のような状態になっていました。
- とりわけVue.js使用箇所でレイアウトシフト等が顕著に発生。コアウェブ指標の改善を狙ってhypernovaを駆使したけど限界があった
- 開発環境でページをリロードしてから表示されるまで30秒近くもかかる。原因を調べたところどうやらSprocketsの処理に時間がかかることが問題とわかったが改修されるめどもなかった
- 消せるか消せないかの判断がつかない大量のCSS(当然、グローバルスコープ)
- 何重にも呼び出したパーシャルの1番最下層で使用される謎のインスタンス変数
- jQuery, SwiperといったjsのパッケージがERBに点在して読み込まれている
- ERB(Ruby)とVue.jsコードを触るため、学習コストが2倍に。エンジニアはキャッチアップできていたものの非エンジニアにとっては二言語覚えなくてはならずハードルが高かった
- Vue.js2 → 3のアップグレードが恐ろしく大変だった。かなりの工数を割いた上にどうしてもエラーが解消しない箇所があり結局アップグレードを完遂できなかった
- もっとモダンな技術使いたいなあ。。というなんとなくのモヤモヤ
まとめると、 「サイトパフォーマンスの悪化」「開発環境の速度低下」「保守性の低下」「開発者の小さなストレスの蓄積」 といった問題が発生していました。(長寿化したプロダクトにあるあるですね)
これらの問題に対して、現状スタックを大きく変えずに各個撃破していく手段は存在すると思います。ただ一方で、どうしても打つ手が小さくなりがちになったり、やってみたはいいがそもそも効果が薄かったりといったリスクもありそうに感じていました。
そういった背景から、全体最適を考えるとフロントエンドの技術スタックを刷新、最新化するのが妥当だと考え、フロントエンドの刷新プロジェクトをスタートしました。
言語選定
言語を選定するにあたって、まず達成したいこと(前提)と制約を洗い出しました。
達成したいこと
- 開発環境を爆速にしたい
- サイトパフォーマンスを上げたい
- 新しいもの使ってワクワクしていたい!
制約
- 簡単なコード修正ならエンジニア以外で完結できる
- コードのメンテナンス性が落ちない
- エンジニアの学習コストや教育コストは最小限に
- アップグレードが容易
- 自分たちでトラブルシューティングができそうと思える程度に情報の量が多い
実際にはこれらの項目をもう少し細かく細分化した上で、それぞれの言語ごとに比較しました。
意外に重要なのがソースコードがどういうふうになるかイメージつけておくことだと思っていて、ここがクリアできるとみんなの共通理解を作りやすく、よくわからなくてなんとなく不安だからといったふんわりしたイメージを打破してプロジェクトを進めやすくすることができると思います。
実際私たちは、ふだんよく修正が入ってみんなが見覚えのあるERBコードをCopilotに食わせてそれぞれの言語だとどう変わるのかイメージしやすい状態にしたりといった工夫をしました。
最終的には以下の理由でNext.jsにすることを決めました。
- Nextの方が情報量が多く、トラブルシューティングがスムーズにできそう
- フレームワークとしての成熟度が高い(枯れている方)
- 学習コストが高いとよく言われるが、コードの複雑性はVueと比較してもそこまで難しくならないようにできそう
理想系と移行方法の検討
コミックフェスタには既に大量のページがあり、ページによってはスマートフォン版とPC版でUIが異なることから、それらを一気に別の言語、アーキテクチャに移行することは相当ハードルが高いと感じていました。開発期間や工数、さらに一気に移行した際の障害発生率等を考えると、ビッグバンリリースは現実的ではありません。
そのため対象端末から移行済ページへのリクエストは再構築したフロントエンド、それ以外のリクエストは元のRailsに振りわけるといったやり方で、段階的に移行していく必要がありました。
最終的に実現方法は、既存のRailsと再構築したNext.jsの前段にCloudFrontとLambda@edgeを配置し、そこで端末とリクエストパスを判別して送信先リソースを振り分けることにしました。
刷新による効果
移行段階は現在初期リリースを終えて、トップページと本棚ページのNext.js切り替えが完了しています。
ここまでである程度見えてきた効果について記載しようと思います。
サイトパフォーマンス
トップページのページスピードインサイト比較がこちらです。(画質粗いです)
正直、想定よりも向上したなという感想です!
ここは嬉しい驚きでした。
数値だけでなく体感面でも改善を感じています。
初期表示時間が 約3 ~ 4秒 → 約 2 ~ 3秒に短縮できたためか、体感だとクリックしてから 「うーーーーーーん、ポン、ポン、、、」 → 「うんポン」くらい早くなったように感じます。
開発環境の速度
ある程度速くなり、ページリロード後表示されるまでの時間にストレスを感じる度合いは減りました。
ただ、SSRの場合はバックエンドのAPIを叩いた後に初期表示されるので、ページにもよりますがそこまでの改善効果を見出すことはできていない状態です(こちらは別途対策が必要)。
番外 学習コスト
実は1番気にしていた言語変更による学習コストですが、エンジニアメンバーのNext.jsへのモチベーションが高かったこともあり、今のところ大きな問題にはなっていません。
残された課題
狙っていた効果はある程度出すことができましたが、まだいくつかの課題が残っています。
API周りの最適化
- 1ページあたり3~10程度の API呼び出しあり。まだ通信数減らせるかも?
- BFF層に関する検討
CloudFrontも含めたキャッシュ戦略
- 減るためコスト削減できる
- パフォーマンスもよくなる
フロントエンドテストない
- 今ひとつもない
- さすがにこのまま行くとちょっとこわい。。
まとめ
今回の刷新プロジェクトにあたって、もちろん簡単なことばかりではありませんでした。
ここでは語り尽くせないような思いもしなかった困難もたくさんありました。
けれどこうしてリリース後に振り返ってみると、そこには確実に自分たちの成果が目にみえる形として残っていて、やりがいを感じると同時に大変嬉しく感じています。
また、困難は人を成長させるとはよく言ったもので、一つの大きなプロジェクトをやり切ったことによって、メンバー一人一人の自信にもつながっているように感じています。
まだまだ課題は山積みですが、私たちならやれると信じて、少しずつ着実にクリアしていければと思っています。
もし一緒に戦ってくれる方がいれば大歓迎です。
最後までお読みくださりありがとうございました。
宣伝
株式会社ウェイブでは、電子コミックやアニメ配信サービスなどを自社開発で運営しております。
新しい技術を積極的に取り入れているモダンな環境が整っているウェイブで一緒に働いてみませんか?
興味ある方は是非こちらをご覧ください!
![wwwave's Techblog](https://storage.googleapis.com/zenn-user-upload/avatar/04957e5dab.jpeg)
株式会社ウェイブのエンジニアによるテックブログです。 弊社では、電子コミック、アニメ配信などのエンタメコンテンツを自社開発で運営しております! ve.jp/service/
Discussion