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

"フロントエンドの技術"を移行する技術 / Frontend Migrations

"フロントエンドの技術"を移行する技術 / Frontend Migrations

フロントエンドカンファレンス東京 2025の資料です。
https://fec-tokyo.github.io/2025/

Avatar for Toshihisa Tomatsu

Toshihisa Tomatsu

September 21, 2025
Tweet

More Decks by Toshihisa Tomatsu

Other Decks in Technology

Transcript

  1. 2 ©Linc' well inc. ⾃⼰紹介 • 外松 俊尚(Toshihisa Tomatsu) •

    株式会社Linc'well • フロントエンド基盤チーム • 愛媛からリモートワーク • X: @toshi__toma
  2. 3 ©Linc' well inc. この発表について カンファレンステーマ:次世代を担うエンジニアに向けて • これまで何度かフロントエンドの技術を移⾏する仕事をした • 経験する中で⾒えてきたもの:移⾏時に考えることやテクニックのパターン

    • ⾃分が⼤事にしてきたもの • 安全にリリース • 効率的に進める • 今⽇は o フロントエンドの技術移⾏はどういったものがあるのか o どういうことを考え、どう進めるのか o 移⾏を実施する際に使えるテクニックを説明 技術選定と⼀緒で、事例と同じ選択はできないが、次に移⾏を担当するときに使える武器を増やす
  3. 4 ©Linc' well inc. ©Linc' well inc. 4 1 フロントエンド技術の移⾏について

    2 移⾏の計画を⽴てる 3 移⾏実施時のテクニック 4 その他Tipsやまとめ
  4. 6 ©Linc' well inc. フロントエンド技術の移⾏例 ⾊々な移⾏事例があり技術ブログなどで紹介されてる • jQuery -> React

    • JavaScript -> TypeScript • Jest -> Vitest • webpack -> Vite • styled-components -> CSS Modules • CSR -> SSR • ESLint Legacy Config -> Flat Config • etc UIライブラリ フレームワーク ⾔語 テストツール ビルドツール スタイリング レンダリング 新しいパラダイム
  5. 7 ©Linc' well inc. どういう時に移⾏が起きる? • ライブラリやフレームワークのEOLやメンテナンス停滞 • より良いソリューションが出てきた •

    開発⽣産性やプロダクト価値向上 • チームのスキルセットとの乖離 • 新メンバーがキャッチアップに時間がかかるマイナーな技術を使っている • 採⽤観点での懸念 • ライブラリの変化への追従 • 例:Reactの新しいパラダイム(Server Components、Suspenseなど)にライブラリが対応できない・相性が悪い
  6. 8 ©Linc' well inc. 技術移⾏の悩み • 書き換える対象が多くて⼤変 • 本番リリースして問題が起きないか不安 •

    何か予期していないことが起きるんじゃないか • 何を確認したら無事にリリースできたと⾔えるんだろう
  7. 9 ©Linc' well inc. 移⾏の特性 その移⾏はどのパターン?それを踏まえて計画するのが⼤事 影響範囲や影響度 • アプリケーションのランタイムに影響するのか •

    開発時にだけ使う技術なのか(devDependency) • アプリケーション全体に影響するのか • どこに影響するのか • ⾒た⽬?ロジック?APIリクエスト?ルーティング? その他 • 段階的に置き換えてリリース可能か • 機械的に置き換え可能か • 問題が起きた時に気付きやすいか • 互換性があるものに移⾏するか
  8. 10 ©Linc' well inc. フロントエンド技術の移⾏例と移⾏の特性(再掲) • jQuery -> React •

    JavaScript -> TypeScript • Jest -> Vitest • webpack -> Vite • styled-components -> CSS Modules • CSR -> SSR • ESLint Legacy Config -> Flat Config • etc 影響範囲や影響度 • アプリケーションのランタイムに影響するのか • 開発時にだけ使う技術なのか(devDependency) • アプリケーション全体に影響するのか • どこに影響するのか その他 • 段階的に置き換えてリリース可能か • 機械的に置き換え可能か • 問題が起きた時に気付きやすいか • 互換性があるものに移⾏するか
  9. 11 ©Linc' well inc. ざっくりとした移⾏の流れ とにかく段階的に移⾏できるかを考える。最初に考えたスコープよりさらに⼩さく出せないか 1. 計画作り 2. 事前準備(テスト拡充・リファクタ)

    3. 移⾏実施 4. テスト(⾃動・QA) 5. リリース(段階的) 6. リリース後の監視 段階的に移⾏できるものは、⼩さく「実施→リリース→監視」を繰り返す
  10. 13 ©Linc' well inc. 移⾏の特性をもとに計画を⽴てる 移⾏の特性で出した観点をもとに、リスクがどれくらいあるか、効率的にできる余地があるかを考える Jest -> Vitestの例 •

    影響範囲や影響度 • テスト全体に影響 • アプリケーションのランタイムには影響しない • 機械的に置き換え可能か • コードの置き換え内容はimportやAPIの互換性がある書き換えが主 • 段階的に置き換え可能か • 新旧それぞれのテストコマンドを⽤意してディレクトリや拡張⼦を区別すれば可能 • 問題が起きた時に気付きやすいか • 問題があるテストは落ちるから気付きやすい リスクが低く、段階的に置き換えるメリットが多くなさそうなので⼀回でAIエージェントで移⾏する選択をとった ※ この選択が正解ではなく、コンテキストによって適切なアプローチは変わる
  11. 14 ©Linc' well inc. 移⾏の特性をもとに計画を⽴てる2 ReactのClassコンポーネント -> Hooksベースの関数コンポーネントの例 • 影響範囲や影響度

    • アプリケーションのランタイムに影響し、実装は⼤きく変わる • 置き換えたコンポーネントが影響範囲 • 機械的に置き換え可能か • 現実的なコードで機械的に適⽤できるものはなく、そもそもパラダイムが違うので機械的に置き換えをするのは不適切 • 段階的に置き換え可能か • コンポーネント単位で置き換え可能 • 問題が起きた時に気付きやすいか • ⾃動テストと動作検証 • そこで気付けないとリリース後にエラーやバグとして気付くことになる 段階的に置き換え可能だが、リリース時のリスクがそこそこ⾼いので、FeatureFlagで新旧実装を切り替えて移⾏
  12. 16 ©Linc' well inc. 何に移⾏するか - 互換性 • jQueryからReactなどは互換性などの概念がないレベルの移⾏だから考慮する余地もない ⼀部、互換性があるようなものがある

    • webpackからの移⾏ • Rspackはwebpack互換を⽬指してるので⼀定互換性がある • 各種設定、webpack pluginの移⾏ • Jestからの移⾏ • VitestはAPIがJestとかなり似てるので⽐較的移⾏が容易にできる
  13. 17 ©Linc' well inc. 何に移⾏するか -技術のスコープ • 技術のスコープを拡⼤したものに移⾏する場合、影響範囲および難易度が上がるので覚悟が必要 例えば、create-react-appが⾮推奨になったことで移⾏する場合、Vite?Next.js? •

    create-react-appのスコープ • 開発サーバーとビルドコマンドの提供 • webpackやbabelのwrapper • Viteの場合はスコープが同じ • 開発サーバーとビルドコマンドの提供 • 内部で使ってるbundlerなどは変わるがスコープは同じ • Next.jsの場合はスコープが広がる • ルーティングやレンダリング⽅式の変化など
  14. 18 ©Linc' well inc. 互換性と技術のスコープ あくまで移⾏時だけの短期的な評価軸なため、それを最優先すべきではないが… • 今はそこにがっつり⼯数を避けない時 • まずは低コストで〇〇の恩恵を享受できないか

    • 中間ステップとして採⽤するのも有効なケースも • まずは低コストで移⾏して痛みを和らげて、⼤きな意思決定の判断までの時間を稼ぐ • ただし、全体の期間が⻑くなったり検証回数が増えることとのトレードオフ
  15. 19 ©Linc' well inc. 対象を集計する 移⾏の計画を⽴てたり、進捗を可視化するためにも、対象を集計する • grep, find •

    任意のツールでjson出⼒してNode.jsのスクリプトで集計 • ESLint • no-restricted-imports • no-restricted-syntax • ASTツール(jscodeshift, GritQL)
  16. 20 ©Linc' well inc. リリースによる影響と監視 何を確認したら無事にリリースできたと⾔えるか、どこで問題に気付くのかを事前に整理する • 元の挙動が壊れない、不具合が出ない • それ以外に、その移⾏は何に影響を与える?

    • パフォーマンス、SEO、ユーザー体験、インフラ • それは、どの値を監視していくのか • 監視ツールがない場合は先にセットアップ 実際にリリースすると、事前に想定していなかった影響が出ることも多い • プロダクトのKPIを監視対象に⼊れると、監視ツールでは⾒えない想定外の問題に気付けることがある
  17. 21 ©Linc' well inc. どう移⾏を実施していくか? • 影響範囲が⼤きい場合どう実施する? • 機会的に置き換えるとは? •

    段階的に移⾏するには? ⾊々なやり⽅があるので、移⾏する技術の特性や影響範囲などに応じて部分的に組み合わせて選択していく
  18. 23 ©Linc' well inc. 画⾯や機能単位での段階的移⾏ アプリケーションレベルの移⾏や影響が⼤きい場合 • 画⾯やパス、機能単位、特定のコンポーネントごとに段階的に置き換える • 切り戻し可能な状態にする

    • 同⼀アプリの中で画⾯単位で移⾏を実施して、問題があれば切り戻すのを許容するケースも多い • リバースプロキシやCDNで画⾯のパスで新旧のアプリケーションを振り分ける⽅法も • ただし制約や考慮事項は多い • 例:jQuery+Rails -> React, RESTからGraphQLへの移⾏
  19. 24 ©Linc' well inc. FeatureFlag • アプリケーション内のコードをFeatureFlagで出し分けて切り戻しができる • ⾃前実装したりSaaS使ったり •

    影響範囲が⼩〜中の場合に使いやすい フラグがON: 〇〇で実装したコンポーネント, フラグがOFF: 旧実装のコンポーネント
  20. 25 ©Linc' well inc. FeatureFlagの例 ReactのClassコンポーネント -> Hooksベースの関数コンポーネントの例 1. 対象にする画⾯や⼤きい粒度のコンポーネントをコピー

    2. Hooksベースのコードを⽤意 3. コンポーネントの上位層にFeatureFlagを⼊れて旧版と新版で切り替えてリリース 4. 問題があった場合はフラグをOFFにする • 他にも、特定の役割を持つライブラリの置き換えなどでも使いやすい • 例: ビデオチャットで使ってるライブラリの置き換え • 新旧のソースコードで追従もれを防ぐためにCODEOWNERS機能を使う 影響範囲は限定的だが、変化が⼤きくバグが出やすい場合に切り戻ししやすい
  21. 26 ©Linc' well inc. ソースコードはそのままで移⾏する ビルドツールなどの移⾏では、アプリのソースコードは変更せず移⾏を⾏う create-react-app ‒> Vite の例

    • アプリ全体に影響するが、段階的にリリースするのが難しい • 問題があったら切り戻したい • ビルドコマンドでどちらで動かすかが切り替わる • まずはVite⽤のコマンドを⽤意 → 同じコードでどっちのビルドも通るように • 先にローカル開発コマンドを⽤意して、有志に触ってもらってバグ検知 • 同じコードで移⾏前・後どちらでも動くように • 環境変数の参照コードなど(既存: process.env.XX, 移⾏後: import.meta.env.XX) • 設定やpluginを⼊れて既存コードを変えなくてもいい形に • 最後のリリース時にビルドコマンドだけ差し替えてリリース
  22. 27 ©Linc' well inc. codemodの活⽤ • コードを⾃動的に変換するスクリプトやツールによる移⾏(code modification) • 正規表現や⽂字列置換では対応できないようなものも⼀括で置き換え可能

    • 置き換えの規則性があり、⽐較的単純なものはまず利⽤を検討する どう使う? • 既存のツールを探す • 〇〇 codemod • codemod.com Registry • ⾃作する
  23. 28 ©Linc' well inc. 既存のツールを探す-codemodの活⽤例 ‒ flowtype -> TypeScript の例

    • Babelが同じようにflowからTSへの移⾏を進めているのを⾒た • flowtsというcodemodツールを利⽤ • monorepoのパッケージ単位で移⾏スクリプトを実⾏ • 1⽇〜⼤きいパッケージでも1週間で対応 • 実際のプロジェクトだとカバーできていない変換パターンがあった • Issueを⽴てたりforkして⼀部修正
  24. 29 ©Linc' well inc. codemodを⾃作する • jscodeshift, ts-morph, eslint fix

    • AST ViewerなどでASTを⾒て実装 • input/outputのfixtureを⽤意して楽にテストできる • ⼀個のスクリプトでいろんな変換をしようとすると難しいので⼩さい単位で • OSSに参考実装はたくさんある • react, next, mui • codemod/commons
  25. 30 ©Linc' well inc. AI or codemod • 今はAIエージェントがあるけど必要? •

    なるべくcodemodを使いたい • AIエージェントは冪等ではないから、レビューでチェックすることになる • ⼤規模な置き換えだと全部しっかりレビューはしんどい • codemodは冪等で⾃動テストで挙動を担保できるので、レビューが⽐較的楽 • AIにcodemodの実装を⼿伝ってもらう ただし • 毎回codemodを⽤意するのは⼤変 • 得意そうなケースではエージェントによる置き換えを試す
  26. 31 ©Linc' well inc. AIエージェントによる移⾏ Jest -> Vitest の例(基盤チームでの取り組み) •

    AIエージェントによる移⾏が⾏いやすかった • 1PRで移⾏するので繰り返し使わない • 単純なAPIの置き換えが主 • 移⾏の成功・失敗が分かりやすい(テストが落ちる) • codemodを⽤意する⼿間が省けた • 置き換えの⼿順書を⽤意して依頼 • Before/Afterのサンプル • 失敗したケースを都度反映して類似箇所を対応 • 部分的に⼿動で修正 • 事前に依存関係の追加や設定ファイルの対応などを⾏った
  27. 33 ©Linc' well inc. AIエージェントで初期検証の速度を上げる • 移⾏では、初期検証をまずやる • 細かいところは気にせず、何が必要で、どういう課題が発⽣するかを⾒つける •

    この初期検証の速度を上げるの有⽤ ⾃分のやり⽅ • NotebookLMで事例の記事などをソースに追加(ソースを探すで検索、URLから追加) • 情報を集めて移⾏ガイドを作ってmarkdownに出⼒ • 移⾏ガイドをローカルのAIエージェントに渡して作業してもらう • 何をやってるか、どこでエラーになるか、どれくらいの作業量かなどを⾒る
  28. 34 ©Linc' well inc. 漸進的な移⾏ • 最初から理想的な状態に移⾏するのではなく、徐々に近づける JavaScript -> TypeScriptの例

    • JavaScriptのまま、JSDocによる型注釈を⼊れて型チェックを⾛らせる • ファイル単位でTypeScript化していく • ⼀旦全部TSに移⾏して、型エラーはanyや@ts-expect-error もちろんトレードオフが結構ある
  29. 36 ©Linc' well inc. codemodでの移⾏時のレビュー • codemodでの移⾏はPRが⼤きくなりがちなのでレビューが⾟い • ⾃動変換とその後の微調整が必要なケースが多い •

    ⾃動ツールと追加修正はコミットは分ける • ⾃動ツールはテストで挙動がある程度保証されてるので、全部⽬視で⾒るがある程度流しで⾒れる • ⼈間による追加修正は正しいかちゃんと⾒る • git diffのSimilarity: -M • 拡張⼦が変わる移⾏で、拡張⼦と少しファイルの中⾝を変えただけで別ファイル扱いになることがある • 差分を⾒るのが難しくレビューしにくくなる • この閾値を調整するとファイルのrenameと判断される時がある
  30. 37 ©Linc' well inc. ビルドによる出⼒の差分があるかチェック • ものによっては移⾏してもビルド結果が変わらないものがある • ビルドの出⼒結果が変わらないなら、安全にリリースできる •

    フロントエンドはビルド結果をデプロイする • ビルド結果のディレクトリのdiff をとる 場合によってはdiffを取れるように • 難読化をOFF • クラス名の⽣成ルールを固定にする • ビルド結果をformatする
  31. 38 ©Linc' well inc. ⾃動テスト • 元の挙動と変わっていないことを保証するために⾃動テストで保証 • 単体テストで保証できる移⾏は限定的 •

    Visual Regression Testing • スタイリングライブラリなど、⾒た⽬が壊れやすいケースなど • メンテナンスまで考慮すると導⼊が⼤変だが、移⾏時にだけ使う使い捨てのテストとしても • 結合テスト、E2E
  32. 39 ©Linc' well inc. 動作確認・QA • DevToolsで検証 • Network, Lighthouse

    • QAメンバーとの連携や事前の調整 • 各チームに協⼒してもらう • モンキーテスト、bug bash会
  33. 41 ©Linc' well inc. その他のおすすめ • 早めの段階からデプロイまでしておく • ⼩さい単位でもいいから、STG環境などにデプロイまではやっておく •

    そこで初めて気が付ける課題やうまくいかないところがある • 移⾏の進捗を可視化する • ゴールを意識、モチベーションを上げる・広げる • findやgrepとかで件数出すだけでもいい • 定期的に⼿動で集計して、スプレッドシートでグラフ出すとかでも • 意思決定や作業過程はドキュメントやメモとして残す
  34. 42 ©Linc' well inc. その他の教訓 • 検討やお試しだけは早めにやっておく • 検討を始めて、もっと早く取り組んで、事前に〇〇をやっておけば。。。がある •

    すぐに実作業に取り組まなくても、素振りだけして解像度を上げておく • 移⾏後の削除はちゃんとやる • 将来のメンバーが過去を知らなくてもいいように • 移⾏のために⼊れた対応 • 名前
  35. 43 ©Linc' well inc. まとめ • “フロントエンドの技術”を移⾏する技術 • どういう特性の移⾏なのかを⾒極める •

    それに合わせた計画を⽴てる • 安全にリリースするために切り戻ししやすい⽅法や効率的な⾃動化⽅法などを紹介 • 移⾏時に考慮することや取れる選択は、プロダクト・組織・既存のコードベースや仕様によって違う • だからこそ、⼿札を多く持つことで、より良い⽅法を選択できる • 次に移⾏をするときの参考になれば嬉しいです
  36. 44 ©Linc' well inc. We are hiring! • 「テクノロジーを通じて医療を⼀歩前へ」をミッションに最⾼の医療体験の提供に取り組んでいます •

    エンジニアを幅広く募集中、特にフロントエンド! • https://recruit.linc-well.com/engineer • カジュアル⾯談やXのDMでも
  37. 47 ©Linc' well inc. コードベースを分割してスコープを狭くする • 巨⼤なコードベースが対象だと難易度が⾼い • コードベースを分割しておくことで、その単位で移⾏や新しい技術を導⼊していく GraphQLのオペレーションファイル

    -> Fragment Colocationベース の例 • codegenの設定を⼤きく変えたいが、rootの全コードベースを対象にすると実施が難しい • コードベースをパッケージとして分割するPJを進めていた • この移⾏だけのためにやったわけではない • 特定のパッケージごとに設定ファイルを置いて、特定のコードベースごとに段階的移⾏が可能になった
  38. 49 ©Linc' well inc. コンフリクトを避ける • コンフリクトはある程度はしょうがない部分はある • ソースコード全体に適⽤するような変更でリスクが少ない場合 かつ

    メインブランチへのマージタイミングが決 まってるケース • 例:formatterの移⾏ • 各エンジニアがメインブランチにマージした後に少し時間をもらって変更を適⽤ • 既に作成済みの未マージPRは個別に相談する必要はある