Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
アンチパターンを避ける型駆動React最適化 (TSKaigi2026 アフターパーティー)
Search
seriseri
June 12, 2026
65
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
アンチパターンを避ける型駆動React最適化 (TSKaigi2026 アフターパーティー)
seriseri
June 12, 2026
More Decks by seriseri
See All by seriseri
アンチパターンを避ける型駆動React最適化
seriseri
0
13
AIに設計を書かせるだけで「理解負債」と「実装漏れ」が激減した話【フロントエンド編】
seriseri
1
150
「shadcn/ui × 自社デザインシステム」実践ガイド──FigmaトークンからTailwindまでの連携術
seriseri
0
19
フロントエンド開発にAIを“仕組みで”組み込む方法
seriseri
0
32
Featured
See All Featured
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
790
How GitHub (no longer) Works
holman
316
150k
Evolving SEO for Evolving Search Engines
ryanjones
0
250
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
610
My Coaching Mixtape
mlcsv
0
230
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
490
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
73
41k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
340
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
68
56k
GraphQLとの向き合い方2022年版
quramy
50
15k
So, you think you're a good person
axbom
PRO
2
2.1k
Transcript
アンチパターンを避け 型駆動 React最適化 PeopleX / 芹澤和也
© PeopleX Inc. 3 アジェンダ 1. React Compilerとは 2. React
Compilerの仕組み 3. 最適化を阻害す アンチパターン 4. 対策
01 React Compilerとは © PeopleX Inc. 4
© PeopleX Inc. 5 React Compilerとは 5 // “とりあえず全部メモ化” 典型
const Row = memo((props) => { const label = useMemo(() => formatLabel(props.user), [props.user]); const onClick = useCallback(() => { props.onSelect(props.user.id); }, [props.user.id, props.onSelect]); return <li onClick={onClick}>{label}</li>; }); ⼿動メモ化のコスト • 依存配列の管理コスト • メモ化漏 、誤メモ化 • レビューコスト • バンドルサイズの肥⼤化
© PeopleX Inc. 6 React Compilerとは ⼿動メモ化 • useMemo •
useCallback • React.memo © PeopleX Inc. 6 こ まで React Compiler 爆誕 コンパイル時の⾃動メモ化 • useMemo • useCallback • React.memo こ から Before • 依存配列の正確さがチームに依存 • 再レンダリングが設計、レビューの中⼼ After • 誰でも • 設計中⼼は責務分離と副作⽤の隔離 React Compilerの登場
© PeopleX Inc. 7 React Compilerとは © PeopleX Inc. 7
とこ でReact Compilerって...
© PeopleX Inc. 8 React Compilerとは © PeopleX Inc. 8
どんなコンポーネントでも 最適化してく ??
© PeopleX Inc. 9 React Compilerとは © PeopleX Inc. 9
NO
© PeopleX Inc. 10 React Compilerとは © PeopleX Inc. 10
「純粋」なコンポーネントだけ 最適化(キャッシュ化)してく
© PeopleX Inc. 11 React Compilerとは © PeopleX Inc. 11
「純粋」= 同じ props を渡せ 必ず同じ結果を返し、レン ダー中に外部 状態を一切書き換えない(副作 用を持たない)コンポーネント こと
02 React Compilerの仕組み © PeopleX Inc. 12
© PeopleX Inc. 13 React Compilerの仕組み コンパイルのパイプライン(実⾏順序) 1. Parse(JSX /
TS → AST) — コードを構⽂⽊に分解す 2. 中間表現の構築 — 解析しやすい中間表現に整え 3. データフロー解析 — 値の依存関係を洗い出す 4. 副作⽤ / 可変性の推論 — 副作⽤がない範囲を⾒極め 5. メモ化境界の挿⼊ — 安全な範囲をキャッシュ化す © PeopleX Inc. 13
© PeopleX Inc. 14 React Compilerの仕組み © PeopleX Inc. 14
」 FunctionDeclaration UserList ├─ params: [ ObjectPattern { users, query } ] └─ body: BlockStatement ├─ VariableDeclarator filtered │ └─ CallExpression users.filter( ArrowFn ) ├─ VariableDeclarator count │ └─ MemberExpression filtered.length └─ ReturnStatement └─ JSXElement <List …/> function UserList({ users, query }) { const filtered = users.filter(u => u.name.includes(query)); const count = filtered.length; return <List items={filtered} total={count} />; } 1. Parse(JSX / TS → AST) — コードを構⽂⽊に分解す ⼊⼒コンポーネント 中間データ:AST(構⽂⽊)
© PeopleX Inc. 15 React Compilerの仕組み © PeopleX Inc. 15
2. 中間表現の構築 — 解析しやすい中間表現に整え 」 bb0 (entry): [1] $0 = LoadProp users.filter [2] $1 = FunctionExpr λ(u) [3] $2 = Call $0($1) ; → filtered [4] $3 = LoadProp $2.length ; → count [5] $4 = JSX <List items=$2 total=$3/> [6] Return $4 中間データ:HIR(SSA / basic blocks) function UserList({ users, query }) { const filtered = users.filter(u => u.name.includes(query)); const count = filtered.length; return <List items={filtered} total={count} />; } ⼊⼒コンポーネント
© PeopleX Inc. 16 React Compilerの仕組み © PeopleX Inc. 16
」 filtered := f(users, query) deps → { users, query } count := f(filtered) deps → { filtered } jsx := f(filtered,count) deps → { users, query } // 末端 JSX users / query に み依存 function UserList({ users, query }) { const filtered = users.filter(u => u.name.includes(query)); const count = filtered.length; return <List items={filtered} total={count} />; } 3. データフロー解析 — 値の依存関係を洗い出す ⼊⼒コンポーネント 中間データ:依存グラフ(reaching defs)
© PeopleX Inc. 17 React Compilerの仕組み © PeopleX Inc. 17
」 filtered := f(users, query) deps → { users, query } count := f(filtered) deps → { filtered } jsx := f(filtered,count) deps → { users, query } // 末端 JSX users / query に み依存 function UserList({ users, query }) { const filtered = users.filter(u => u.name.includes(query)); const count = filtered.length; return <List items={filtered} total={count} />; } 3. データフロー解析 — 値の依存関係を洗い出す ⼊⼒コンポーネント 中間データ:依存グラフ(reaching defs) 入力にしか依存していないことがわかる = 純粋
© PeopleX Inc. 18 React Compilerの仕組み © PeopleX Inc. 18
「純粋」= 同じ props を渡せ 必ず同じ結果を返し、レン ダー中に外部 状態を一切書き換えない(副作 用を持たない)コンポーネント こと
© PeopleX Inc. 19 React Compilerの仕組み © PeopleX Inc. 19
」 filtered := f(users, query) deps → { users, query } count := f(filtered) deps → { filtered } jsx := f(filtered,count) deps → { users, query } // 末端 JSX users / query に み依存 function UserList({ users, query }) { const filtered = users.filter(u => u.name.includes(query)); const count = filtered.length; return <List items={filtered} total={count} />; } 3. データフロー解析 — 値の依存関係を洗い出す ⼊⼒コンポーネント 中間データ:依存グラフ(reaching defs) 入力にしか依存していないことがわかる = 純粋
© PeopleX Inc. 20 」 React Compilerの仕組み © PeopleX Inc.
20 4. 副作⽤ / 可変性の推論 — 純粋性を満たす範囲を特定 5. メモ化境界の挿⼊ const $ = _c(5); // useMemoCache let filtered; if ($[0] !== users || $[1] !== query) { filtered = users.filter(u => u.name.includes(query)); $[0]=users; $[1]=query; $[2]=filtered; } else filtered = $[2]; const count = filtered.length; let t; if ($[3] !== filtered) { t = <List items={filtered} total={count}/>; $[3]=filtered; $[4]=t; } else t = $[4]; return t; 出⼒:メモ化済みコード
03 最適化を阻害す アンチパターン © PeopleX Inc. 21
© PeopleX Inc. 22 コンパイラに諦めら 3つのパターン © PeopleX Inc. 22
1. 副作⽤の混⼊ 2. ミュータブル操作 3. ⾮決定的な依存
© PeopleX Inc. 23 コンパイラに諦めら 3つのパターン © PeopleX Inc. 23
1. 副作⽤の混⼊ 2. ミュータブル操作 3. ⾮決定的な依存 」 function Total({ items }) { const total = items.reduce(...); logger.info(total); // I/O return <p>{total}</p>; }
© PeopleX Inc. 24 コンパイラに諦めら 3つのパターン © PeopleX Inc. 24
1. 副作⽤の混⼊ 2. ミュータブル操作 3. ⾮決定的な依存 」 function Profile({ user }) { user.name = user.name.trim() return <h1>{user.name}</h1>; }
© PeopleX Inc. 25 コンパイラに諦めら 3つのパターン © PeopleX Inc. 25
1. 副作⽤の混⼊ 2. ミュータブル操作 3. ⾮決定的な依存 」 function Token() { const id = Math.random(); return <p>{id}</p> }
04 対策 © PeopleX Inc. 26
© PeopleX Inc. 27 対策 © PeopleX Inc. 27 1.
型で防ぐ 2. Lintで防ぐ 3. 設計で防ぐ 4. ランタイムでの確認 // props を deep readonly で受ける type Props = { items: ReadonlyArray<Item>; user: Readonly<User>; }; function List({ items }: Props) { items.push(...) // ✕ コンパイルエラー const next = [...items, x]; // ◦ }
© PeopleX Inc. 28 コンパイラに諦めら 4つのパターン © PeopleX Inc. 28
1. 副作⽤の混⼊ 2. ミュータブル操作 3. 参照不安定性 4. ⾮決定的な依存 」 function Profile({ user }) { user.name = user.name.trim() return <h1>{user.name}</h1>; } こ を防ぐ!
© PeopleX Inc. 29 対策 © PeopleX Inc. 29 1.
型で防ぐ 2. Lintで防ぐ 3. 設計で防ぐ 4. ランタイムでの確認 // props を deep readonly で受ける type Props = { items: ReadonlyArray<Item>; user: Readonly<User>; }; function List({ items }: Props) { items.push(...) // ✕ コンパイルエラー const next = [...items, x]; // ◦ }
© PeopleX Inc. 30 対策 © PeopleX Inc. 30 1.
型で防ぐ 2. Lintで防ぐ 3. 設計で防ぐ 4. ランタイムでの確認
© PeopleX Inc. 31 対策 © PeopleX Inc. 31 Biome
Rust 製 高速 Lint / Formatter • noParameterAssign — 引数 再代入を禁止 • useReadonlyClassProperties — 不変表明を強制 • noUselessFragments / noUselessRename — render を清潔に保つ Oxc Rust 製 オールインワン JS/TS ツールチェイン • oxlint react-hooks/* — フック規約を高速検査 • react_compiler 互換ルール — 副作用混入を検出 Lintで防ぐ
© PeopleX Inc. 32 対策 © PeopleX Inc. 32 1.
型で防ぐ 2. Lintで防ぐ 3. 設計で防ぐ 4. ランタイムでの確認 純粋層 / 副作用層 / UI 層を物理的に分ける • 純粋層(Domain) ◦ 純粋関数 / 不変データ • 副作用層(Effects) ◦ I/O / fetch / storage / log ◦ 副作用 専用フック・サービスに隔離 • UI層 ◦ JSX / Server Components ◦ 純粋層 値をただ描画するだけ
© PeopleX Inc. 33 対策 © PeopleX Inc. 33 1.
型で防ぐ 2. Lintで防ぐ 3. 設計で防ぐ 4. ランタイムでの確認 純粋層 / 副作用層 / UI 層を物理的に分ける • 純粋層(Domain) ◦ 純粋関数 / 不変データ ◦ Compiler が最適化できる純粋層 • 副作用層(Effects) ◦ I/O / fetch / storage / log ◦ 副作用 専用フック・サービスに隔離 • UI層 ◦ JSX / Server Components ◦ 純粋層 値をただ描画するだけ コンテナ・プレゼンターパターン (+hooks)
© PeopleX Inc. 34 対策 © PeopleX Inc. 34 1.
型で防ぐ 2. Lintで防ぐ 3. 設計で防ぐ 4. ランタイムでの確認
35