Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

事例 - AKE

Slide 12

Slide 12 text

事例 - ML Platform

Slide 13

Slide 13 text

事例 - IAM

Slide 14

Slide 14 text

チーム体制

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

サービス:エンジニア =

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

/(^o^)\

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

なぜNext.jsを使うのか

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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で賄える

Slide 33

Slide 33 text

App Router化までの道のり

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

🏃App Router化開始🏃

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

Middlewareを用いてみる

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

結果と所感

Slide 50

Slide 50 text

バンドル結果 (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 →だが、ある程度サーバーサイドに持っていけた

Slide 51

Slide 51 text

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の効果かもしれない

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

今後の展望

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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