ハウテレビジョン技術ブログ

『外資就活ドットコム』『外資就活ネクスト』『mond』を開発している株式会社ハウテレビジョンの技術ブログです。

【開発Days vol.5】求人詳細Next.js移植

外資就活ネクストの開発チームです。

開発チームの新たな取り組み "開発Days"とはで紹介されたように、弊社では毎月連続した2日間、通常のプロダクト開発から一時的に離れ、技術的な課題に集中的に取り組む仕組みがあります。

今回は、その開発Days vol.5で取り組んだ「求人詳細ページのNuxt.jsからNext.jsへの移植」についてご紹介します。

背景: フレームワークをまたぐ遷移のローディング問題

外資就活ネクストでは、Nuxt.js(Vue)からNext.js(React)へのフロントエンド移行を段階的に進めています。本番環境ではCloudFrontの背後にAPI Gatewayを配置し、URLパスに基づいてNext.js(ECS上のALB経由)とNuxt.js(NLB経由)にリクエストを振り分けることで、2つのフレームワークを共存させています。

この構成で問題になるのが、フレームワーク境界をまたぐページ遷移のローディング時間です。

例えば、Next.jsで実装されたスカウト画面から、Nuxt.jsで実装された求人詳細ページに遷移する場合、体感で明らかに遅いローディングが発生します。これには複数の技術的要因があります。

SPA遷移ではなくフルページリロードになる

同一フレームワーク内の遷移はSPA(Single Page Application)として動作し、差分のみを描画するため高速です。しかし、異なるフレームワーク間のNext.js→Nuxt.jsの遷移では、ブラウザが完全に新しいHTMLドキュメントを取得します。これはユーザーにとって「別のサイトに移動した」のと同じ体験です。

別フレームワークのJSバンドル全体を再ダウンロード

Next.jsのページを表示している状態では、ReactのランタイムやTailwind CSSなどがブラウザに読み込まれています。Nuxt.jsのページに遷移すると、これらは一切再利用できず、Vue 3のランタイム、Vuetify、Piniaといった別のフレームワーク一式をゼロからダウンロード・パースする必要があります。

Hydration(初期化処理)のやり直し

サーバーサイドレンダリングされたHTMLをインタラクティブにするhydration処理も、フレームワークごとに独立して実行されます。セッション情報やUI状態も共有できないため、認証チェックやユーザー情報の取得もゼロからやり直しです。

これらが積み重なることで、フレームワーク境界の遷移は同一フレームワーク内の遷移と比べて体感で数倍のローディング時間がかかっていました。

やったこと: 求人詳細ページをNext.jsに移植

求人詳細は外資就活ネクストの中でもアクセス数の多い重要なページです。スカウトや求人検索など、すでにNext.jsで実装されたページからの流入が多く、フレームワーク境界の遅延を最もユーザーが感じやすい箇所でした。

デザインは変更せず、Nuxt.js版と同じ見た目のままNext.jsに移植する方針としました。開発Daysの2日間で、チーム4名で分担して10個以上のコンポーネントを並行開発しました。

コンポーネント構成

ページ全体をパンくずリスト、ヘッダー画像、タイトル・企業情報、仕事内容、年収テーブル、担当エージェント、類似求人リスト、人気ランキング、応募フッターなど10個以上のコンポーネントに分割しました。

Next.js App RouterのServer Component / Client Componentの境界を意識して設計しています。求人詳細のデータフェッチとレンダリングの大部分はServer Componentで完結させ、ユーザーインタラクションが必要な応募ボタンや類似求人リスト、GAイベント送信などのみをClient Componentとして分離しています。

ルーティングの切り替え

ローカル開発環境ではNginxの設定で /job_infos のルーティング先を変更しますが、本番環境ではTerraformで管理しているALBのリスナールールを変更することで、Next.jsへの切り替えが完了します。

開発中にハマったこと

Stickyフッターとの格闘

求人詳細ページの下部には、画面追従する応募フッターがあります。Nuxt.jsではVuetifyの仕組みで自然に動作していましたが、Next.jsでは自前で実装する必要がありました。

当初は position: fixed + createPortal でbody直下にレンダリングする方法を試みましたが、SSRとのhydration不一致、SPでのBottomNavigationとの重なり、横スクロールの発生と問題が次々に発生しました。

結局、Nuxt版と同じ position: sticky; bottom: 0 に落ち着きました。最初から元実装を忠実に再現する方が速かったという教訓です。

類似求人ダイアログのカルーセル実装

応募完了後に表示される類似求人ダイアログには、PCではカルーセル(2件ずつページング+左右矢印+ドットインジケーター)が含まれます。Nuxt版ではVuetifyのCarouselコンポーネントを使っていましたが、Next.js側ではtranslateXベースのアニメーションを自前で実装しました。flexトラック幅の計算やgrid blowoutの防止など、CSS周りで意外と手こずりました。

まとめ

開発Daysの2日間で大半の実装を完了し、その後のQAとバグ修正を経てリリースしました。移植後は、スカウト画面や求人検索結果から求人詳細への遷移がSPA内遷移として動作するようになり、ローディングの体感速度が大きく改善されています。

Nuxt.jsからNext.jsへの段階的移行は、完了するまでの間ユーザーにフレームワーク境界の遅延を感じさせるという課題を持ちます。今回のように、アクセス数が多く他のNext.jsページからの流入が多いページを優先的に移植することで、移行期間中のUXを効果的に改善できます。


弊社では、一緒に技術的な課題に取り組んでくれるエンジニアを募集中です!

現在募集中の採用情報の詳細は下記をご覧ください。

herp.careers