Upgrade to Pro — share decks privately, control downloads, hide ads and more …

プライベートクラウドのコンソール画面をNext.jsのApp Routerでフルリプレイスした話

did0es
December 12, 2023

プライベートクラウドのコンソール画面をNext.jsのApp Routerでフルリプレイスした話

CyberAgent group Infrastructure Unit(CIU)では、プライベートクラウドのWeb UI開発にNext.jsを用いています。 今回はCIUのフロントエンド組織の現状についてお話した後

・なぜNext.jsを使うのか
・古いNext.js製サービスをどのようにApp Router化したのか

以上を中心に、CIUのフロントエンド組織の今後の技術戦略などについて、Muddyな内容を織り交ぜながらお話します。

Event Page: https://cyberagent.connpass.com/event/301089/

did0es

December 12, 2023
Tweet

More Decks by did0es

Other Decks in Technology

Transcript

  1. プライベートクラウドの
    コンソール画面を
    Next.jsのApp Routerで
    フルリプレイスした話
    株式会社サイバーエージェント
    Shuta Hirai

    View full-size slide

  2. 1. CIUフロントエンドについて
    2. なぜNext.jsを使うのか
    3. App Router化までの道のり
    4. 結果と所感
    5. 今後の展望

    View full-size slide

  3. Shuta Hirai
    株式会社サイバーエージェント
    グループIT推進本部
    CyberAgent group Infrastructure Unit(CIU)
    フロントエンド寄りエンジニア
    Meguro.es 主催
    GitHub : https://github.com/shuta13
    X(Twitter) : https://twitter.com/did0es

    View full-size slide

  4. CIUフロントエンドに
    ついて

    View full-size slide

  5. インフラの組織でフロントエンド?

    View full-size slide

  6. CIUフロントエンドのタスク
    =

    View full-size slide

  7. CIUフロントエンドのタスク
    = プライベートクラウドや
     その関連サービスの開発・運用

    View full-size slide

  8. CIUフロントエンドの役割
    =

    View full-size slide

  9. CIUフロントエンドの役割
    = Web UIの提供で利用者層を増加

    View full-size slide

  10. CLIツールのWeb UIの開発
    (aws, gcpなどのサービスの画面を
    想像してください)

    View full-size slide

  11. 事例 - AKE

    View full-size slide

  12. 事例 - ML Platform

    View full-size slide

  13. 事例 - IAM

    View full-size slide

  14. チーム体制

    View full-size slide

  15. チーム体制
    =マネージャーx2・エンジニアx2

    View full-size slide

  16. サービス:エンジニア
    =

    View full-size slide

  17. サービス:エンジニア
    = 10 : 1(サービス数は20↑個)

    View full-size slide

  18. フロントエンドエンジニアが少ない

    View full-size slide

  19. フロントエンドエンジニアが少ない
    →フロント以外が開発に入る
     あるいは外注

    View full-size slide

  20. フロントエンドエンジニアが少ない
    →フロント以外が開発に入る
     あるいは外注
    →それでもサービスの質を
     落としたくない

    View full-size slide

  21. サービスの品質維持の取り組み
    ・コードの自動生成←前回
    ・Next.jsの採用と追従
    ・クリーンアーキテクチャによる抽象化
    ・UI・APIの型などを含むSDKの開発
    など

    View full-size slide

  22. speakerdeck
    前回(コードの自動生成)

    View full-size slide

  23. サービスの品質維持の取り組み
    ・コードの自動生成
    ・Next.jsの採用と追従←今回
    ・クリーンアーキテクチャによる抽象化
    ・UI・APIの型などを含むSDKの開発
    など

    View full-size slide

  24. なぜNext.jsを使うのか

    View full-size slide

  25. ※特に関係ないです
    https://leerob.io/blog/using-nextjs

    View full-size slide

  26. CIUフロントエンドチームの方針

    View full-size slide

  27. 誰もが一定の品質で
    Cycloud のサービスのWeb UIを
    実装できるようにする

    View full-size slide

  28. Web技術からCycloudに
    必要なものを取捨選択しつつ
    Web技術の進化に追従する

    View full-size slide

  29. Next.jsの採用と追従
    Next.jsを使うワケ
    ・Next.js自体がReactのベストプラクティスを体現しているため
     ・使えば誰もがベストプラクティスを実践できる
     ・SSRやRouting、ビルドで手を抜くためだけのFWではなくなった
     ・Reactの破壊的変更をある程度吸収してくれる
    ・ベンダーロックインが...とか言われるが...
     ・Vercel以外のコンテナ・サーバーレス等で困らない程度には動く

    View full-size slide

  30. Next.js is a shock absorber
    Next.jsは「Reactの緩衝材」として使う
    ・あくまでReactのAPIの抽象化層とみなす
    ・当然使わない機能もある
     ・例えば
      ・fetch(クライアントサイドfetchで代用)
      ・middlewareによるproxy(API Routesかnext.config.jsで代用)
     ・Next.jsを知らない人が見て一目で分かるかをもとに取捨選択

    View full-size slide

  31. Next.jsの運用
    CIUではNext.jsサーバーをCloud Run上に立てている
    ・なるべくCSRに寄せているので、これで十分
    確かにVercelが欲しくなる場面もあるが、限定的
    ・Pages Router時代のISRなどのNext.jsの機能
     ・やろうと思えば他のベンダーでも出来る
    ・CI/CDの最適化
     ・CIUではmyshoes(self-hosted runner)で改善を図っている
    ・Edge Network
     ・CFなど、CDNで賄える

    View full-size slide

  32. App Router化までの道のり

    View full-size slide

  33. App Router化の動機
    ・フロントエンドの技術的成長
     ・ReactのRSCに対する知見を深め、新たなベストプラクティスを構築する
     ・Next.jsを介して使うことで、RSCの大幅な変更に追従しやすく
    ・Dynamic Renderingから、Static Rendering前提に変わった
     ・CSR前提のWeb UIにとっては都合が良い
    ・Next.jsがApp Router前提の機能開発に寄せ始めた
     ・Pages Routerからは使えないAPIが出始めた

    View full-size slide

  34. App Router化するサービス
    Cycloud IAMというCycloudの統合認証基盤のWeb UI
    ・Cycloudユーザー向け
    ・既にCLIが整備されている
    ・ちょうどPages Routerで作りかけのWeb UIがあった

    View full-size slide

  35. 🏃App Router化開始🏃

    View full-size slide

  36. next v13へ更新
    v12をからv13へ更新
    ・v13移行向けのcodemodを利用
    ・変換漏れは手作業で修正
    reactとreact-domもv16からv18へ更新
    ・import React from “react” を codemod で抹消

    View full-size slide

  37. pages to app
    migrating-from-pages-to-app を参考に進める
    ・空の/appを作成し、そこにファイルを移動させる
     ・/pagesと/appは共存できるので↑が楽
    ・_documentと_appは残したままで進め、最後にRoot Layoutに移行

    View full-size slide

  38. “use client” ディレクティブ追加
    pages to app中に “use client” が無い旨のエラーが出るので手作業で修正
    ・シェルなどで全TSXファイルに機械的に追加はしない
     ・パフォーマンスの観点から積極的にSCを利用する
    ・CCはSCを含めないので、適宜propsにchildrenを追加する

    View full-size slide

  39. RSCに対応していないライブラリ
    ライブラリによってはRSCに対応していないReactで書かれている
    ・一旦importして、”use client” をつけて re-export
    ・ちなみにMUIとNextUIをこれで使っていた
     ・後者の更新がつらいので、内製のUIライブラリに移行中
     ・Testingのため、RSCではないReact Componentに分離してテストしてから輸入

    View full-size slide

  40. getInitialPropsの移行
    一部のページで使用していたため、Next.jsのfetchで置き換えた
    ・が、キャッシュの扱いが微妙なので廃止
    ・基本CSRで、SWRをラップしたHookを用いてクライアントサイドでfetch
     ・ちなみにクライアントfetchはNext.jsによって拡張されない
      ・SWRに依存したくなければuseEffect内でfetchすればいい
      ・状態管理にSWRを使っている & fetchの重複排除などがほしいので
       APIを叩く用途にも使用した

    View full-size slide

  41. API Routes to Route Handlers
    pages/api から app/XXX/route に移行
    ・書き方が若干変わるので、手作業で修正
    ・認証に使用しているnext-authも移行
     ・next-auth側でApp Routerは 対応済み

    View full-size slide

  42. HTTP Proxy Middlewareやめる
    CORSを避けるための next-http-proxy-middleware が使えなくなった
    ・Route Handlersではres, reqがimmutableになった
     ・上記のHTTP Proxyは2つを上書きする
    ・そもそもNext.jsのconfigで出来た

    View full-size slide

  43. の移行
    next/head を用いた記述を移行
    ・`export const metadata` をページ内に記述
     ・UIの実装に専念できるようになった
     ・その反面、HTMLらしい文法からは離れてしまった
      ・JS Objectなので宣言的さは失われてないが...

    View full-size slide

  44. i18n対応
    useLocale というカスタムフックが useRouter の仕様変更で使えなくなった
    ・localeがrouterに乗らなくなった

    View full-size slide

  45. Middlewareを用いてみる

    View full-size slide

  46. Middlewareでリダイレクトする場合以外への対応
    ・言語のSwitch UIなど
    ・useContextをラップしたものに書き換え
     ・Provider経由で辞書を渡して、useLocaleでreadする
    useLocaleを変更

    View full-size slide

  47. i18n対応(断念)
    エラーページ(404, 500など)がi18n対応できない
    ・https://github.com/vercel/next.js/discussions/12477
    ・優先度は低いが、対応できないならそもそも移行しないほうが良い判断に
     ・app/[lang]にするパターンより、localStorageに持ったほうが楽そう
     ・i18nライブラリが成熟するのを待って良い

    View full-size slide

  48. 結果と所感

    View full-size slide

  49. バンドル結果
    (nextのbundle analyzerで計測)
    Pages Router製サービス(AKE)
    ・クライアント:サーバー = 2.45MB:2.23MB 計 4.67MB
    App Router製サービス(IAM)
    ・クライアント:サーバー = 2.57MB:3.4MB 計 5.97MB
    全体の容量は増えているが、App Routerでクライアント < サーバーができた
    →増えた要因は内製したUIなどのSDK
    →だが、ある程度サーバーサイドに持っていけた

    View full-size slide

  50. Lighthouse
    (3回計測した平均スコア 計測対象はTOPのリスト表示ページ)
    Pages Router製サービス(AKE)
    ・Perf:A11y:BP:SEO = 84:74:100:91
    App Router製サービス(IAM)
    ・Perf:A11y:BP:SEO = 99:87:100:82
    参考程度ではあるが、パフォーマンスが向上した
    →Speed Indexが大幅に改善(4.8s→0.4s)
    →RSCというより、Static Renderingの効果かもしれない

    View full-size slide

  51. 良かった点
    ・フォルダの表現力が向上した
     ・Route GroupsでUIワイヤーを構成に反映
     ・Private Foldersでページに閉じたコンポーネント・API作成
    ・RSCの使い方や仕組みをインプットできた
     ・なにそれおいしいの?レベルから脱却
     ・べスプラも(多少)構築できた
      ・”use client”を入れる位置を限定する
      ・Server Componentであれば容量大きめのライブラリを import できるなど

    View full-size slide

  52. イマイチな点
    ・ライブラリの追従
     ・API Routesにがっつり依存しているライブラリ(next向けhttp proxyなど)は
      軒並み動かなかった
     ・testing-libraryでTestingもできない
    ・パフォーマンス
     ・(fetch 向けに)force-dynamicをつけると悪化した
     ・↑fetchのcacheを無効化するが、ページ全体がDynamic Renderingされていた
    ・i18n対応
     ・エラー系のページどうするの

    View full-size slide

  53. 今後の展望

    View full-size slide

  54. やりたいこと
    ・fetchの仕組みの調査
     ・(ISRなら)キャッシュが危険そう & 従来のfetchと異なる動きをするため使ってない
      ・が、正体がわかれば使って良さそう
    ・Server Actionsのべスプラの考察
     ・Next.js v14への更新
    ・create-next-app を内製
     ・CLIからコマンド1つでWeb UIを作れるように
     ・Goで書いてます

    View full-size slide

  55. 次回
    次回(いつ?)はフロントエンドエンジニア、あるいはエンジニア以外でも
    Web UIを実装できる化するためのエンジニアリングの話をします
    ・✅ コードの自動生成
    ・✅ Next.jsの採用と追従
    ・クリーンアーキテクチャによる抽象化
    ・UI・APIの型などを含むSDKの開発←メイン

    View full-size slide

  56. ご清聴ありがとうございました

    View full-size slide