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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
seriseri
June 12, 2026
51
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
11
AIに設計を書かせるだけで「理解負債」と「実装漏れ」が激減した話【フロントエンド編】
seriseri
1
150
「shadcn/ui × 自社デザインシステム」実践ガイド──FigmaトークンからTailwindまでの連携術
seriseri
0
17
フロントエンド開発にAIを“仕組みで”組み込む方法
seriseri
0
31
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
3
1.1k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Tell your own story through comics
letsgokoyo
1
1k
Facilitating Awesome Meetings
lara
57
7k
For a Future-Friendly Web
brad_frost
183
10k
Designing Powerful Visuals for Engaging Learning
tmiket
1
450
Java REST API Framework Comparison - PWX 2021
mraible
34
9.5k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.7k
Between Models and Reality
mayunak
4
370
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1k
GitHub's CSS Performance
jonrohan
1033
470k
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