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
Reconciliationの世界
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
did0es
November 01, 2024
Technology
17
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Reconciliationの世界
ReactのReconciliationについて深ぼる話です
did0es
November 01, 2024
More Decks by did0es
See All by did0es
TypeScript Compiler APIとPHP-Parserを活用し、TypeScriptとPHPで型を共有する
shuta13
1
490
ブラウザの投機的読み込みと投機ルールAPIを理解し、Webサービスのパフォーマンスを最適化する
shuta13
3
330
うわっ...私のSwagger、古すぎ...?grpc-gateway向けのSwaggerと向き合う
shuta13
0
150
ViteとTypeScriptのProject Referencesで 大規模モノレポのUIカタログのリリースサイクルを高速化する
shuta13
3
360
歴代のWeb Speed Hackathonの出題から考えるデグレしないパフォーマンス改善
shuta13
8
860
なぜクラウドサービスで Web コンソールを提供するのか
shuta13
4
2.5k
5分でわかるPreactのVDOMで作るWebエディタ
shuta13
0
270
TailwindCSSでUIライブラリを作る際のハマりどころ
shuta13
0
810
codemodとうまく付き合うには
shuta13
0
3k
Other Decks in Technology
See All in Technology
protovalidate-es を導入してみた
bengo4com
0
170
Chainlitで作るお手軽チャットUI
ynt0485
0
210
LLMと共に進化するプロセスを目指して
ymatsuwitter
13
4.1k
攻撃者視点で考えるDetection Engineering
cryptopeg
2
1.4k
EventBridge Connection
_kensh
5
700
FDE という解 ― 暗黙知と明示知をつなぐ、伴走型エンジニアリング ―
otanet
0
140
プロダクト開発から業務改善コンサルまで。事業全体へ「染み出す」ことで広がるエンジニアの可能性
ham0215
0
110
非定型業務をAI slackbotで自動化する ~ 社内要望を自動壁打ちするbotを作った ~/automating-ad-hoc-work-with-ai-slackbot
shibayu36
0
630
2026TECHFRESH畢業分享會 - Lightning Talk - 資料也要 CI/CD? 用 Airbyte 自動化資料同步
line_developers_tw
PRO
0
870
2026TECHFRESH畢業分享會 - AI 時代的人生存檔點
line_developers_tw
PRO
0
890
手塩にかけりゃいいってもんじゃない
ming_ayami
0
510
AIソロプレナー時代に2ヶ月で20人増員した事業創造会社の開発組織の話
miyatakoji
0
610
Featured
See All Featured
Mind Mapping
helmedeiros
PRO
1
250
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Are puppies a ranking factor?
jonoalderson
1
3.5k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Code Review Best Practice
trishagee
74
20k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
160
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.3k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
130
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
310
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
170
Transcript
Reconciliationの世界 CAM, Inc. Creative Division 平井 柊太
自己紹介 平井 柊太(#times_hirai_shuta) 22卒・フロントエンドエンジニア 得意:夜型の生活 苦手:朝全般・花粉 学生の頃は機械学習の研究をして 遊んでました OSS 関連を細々とやってます
GitHub: shuta13 2
本日お話すること 1. Reconciliationとは 2. React Reconciler 3. Reactを再現する 4. 余談
5. 応用 6. まとめ 3
❏ ReactとReconciliationの 仕組みを知る ❏ 仮想DOMの正体を知る ❏ TypeScriptの型システムの 健全性を知る 4 ねらい
Reconciliationとは 5
本資料におけるReconciliation ⇒ 差分検出処理 ❏ “前(old)”と“後(new)”の2つの差分を取る(diff)処理のこと ⇒ 木構造の比較 ❏ DOMに対応する何かしらの木構造体 ❏
計算量(オーダー : O)はどう抑え込む? ❏ 愚直にやるとn個のノードに対してO(n^3) ❏ 頭の体操:1000個のノードだと計算量は?→ 6
React Reconciler 7
ReactのReconciliation 以下2つによりO(n)まで計算量を抑え込む ❏ 異なる型(type)の2つの要素は異なるツリーを生成する ❏ e.g. div と span は異なるツリーを生成する
❏ 特定のプロパティ( props )を与え、子要素が変更される可能性を検知する ❏ 特定のプロパティ ⇒ key ❏ 配列の並び替えを効率よく行うためにこのような識別子が必要 ❏ 無駄な reconciliation を抑制できて Happy 8
ReactのReconciliationにおけるデータ構造 reconciliationとは雑に表現すると「木構造の比較を再帰的に行う処理」 Stack(React <= 16) ❏ 差分検出を中断不可能かつ同期的に処理する Fiber(React > 16)
❏ 差分検出を小分けにする ❏ 小分けにしたものに優先順位をつけ、非同期的に処理する 9
React を再現する 10
※ 具体的な実装を載せると長いので どういったものを実装するかを話します 11
Reactが動く流れ ❏ React要素を生成 ❏ State更新のタイミングでreconciliation ❏ タイミング : setState が
call された瞬間 ❏ 前と後の要素ツリーを比較し、更新・削除 ❏ 親から子に対して繰り返す ❏ 更新済みの要素ツリーをDOMもしくは他のツリーに反映 ❏ React 要素を元の形に整形して Root Container に Attach ❏ DOM 以外もある ⇒ React Native, React Three Fiber 12
JSX(React JavaScript Markup) ❏ Reactの特徴の1つである宣言的UIの実現 ❏ JSXはそのままでは動かない ❏ あくまで React.createElement
の Syntax Suger ❏ Babel, TSC などで JS に変換する ❏ Transpiler, Compiler によるが大抵変換先を変更できる(応用) 13
ほしいものリスト ❏ DOM に対応した木構造( React 要素 )にするもの ❏ React 要素を差分検出するもの
❏ React 要素をレンダリングするもの 14
ほしいものリスト ❏ DOM に対応した木構造(React 要素)にするもの ⇒ React(createElement) ❏ React 要素を差分検出するもの
⇒ react-reconciler ❏ React 要素をレンダリングするもの ⇒ ReactDOM(render) 15
React(createElement) ❏ JSXをTranspileすると得られる createElement 関数の実装 ❏ createElement(type, props, children) ❏
type [string | Function]: HTMLElement の名前もしくは Functional Component ❏ props [object]: key や ref などの Props ❏ children [Array<Element>]: 子要素の配列 ❏ この関数は DOM と1対1対応のオブジェクトを返す ❏ いわゆる仮想DOM ❏ ただの JS オブジェクト 16
react-reconciler ❏ fiberという単位で小分けにして時間をずらしながら実行 ❏ fiber は小分けにし、次に作業を行う要素を簡単に見つけるためのデータ構造 ❏ fiber は child,
parent, sibling へのリンクを持っている ❏ child, siblingが無い場合、parentのsiblingに移動していく ❏ parentにsiblingが無い場合はrootに向かってさかのぼっていく 17
ReactDOM(render) ❏ React 要素から生成した DOM を root の DOM(container) に反映する
❏ ReactDOM.render(<App />, document.getElementById(“root”)) ❏ propsからarrtibuteやeventの登録 ❏ HTMLElementの挿入 ❏ 差分検出処理もここで呼び出す 18
ここまでで一旦Reactの話終了 詳しく : https://github.com/shuta13/react-deep-dive/ 19
余談 - @types/react 20
@types/reactの興味深い点 ❏ bivarianceHack という TypeScript の型システムを悪用した実装がある ❏ 何が嬉しい : メソッドの性質を利用して関数に双変性を持たせられる
❏ bivariance = 双変 ❏ 双方に代入可能であるかつ、サブセットも同様の性質をもつということ ❏ A ⇔ B ならば P<A> ⇔ P<B> ❏ この項における決まり ❏ Aは広い型、Bは狭い型とする(e.g. type A = number; type B = 1; ) ❏ 矢印を右のように定義する : ⇔は双変、⇒は共変(covariance)、⇐は反変(invariance) ❏ 「矢印の先は矢印の元に代入が可能」と読む 21
TypeScriptの型システムにおける矛盾 ❏ TSでは配列を共変(A ⇒ B)として扱っている ❏ number ⇒ 1 ならば
Array<number> ⇒ Array<1> ❏ 通常、メソッドの引数は反変(A ⇐ B)なのでメソッドは反変 ❏ number ⇒ 1 ならば (arg: number): void ⇐ (arg: 1): void ❏ Array<number>.push() ⇐ Array<1>.push() は成り立つ? → いいえ ❏ メソッドは反変のはずだが、Arrayが共変であるため代入不可能 ❏ TSではこの代入が可能 ❏ つまりメソッドを双変として扱っている 22
TypeScriptにおけるメソッドと関数の扱い ❏ TSではメソッドと関数を区別している ❏ メソッドは双変、関数は反変 ❏ type Func = {
foo: (a: A) => void } と type Method = { foo(a: A): void } は別物 ❏ しかし Method から foo を取り出す( Method[“foo”] )と関数扱いになる ❏ 型としては関数だが、メソッドとしての性質は残る ❏ つまり双変な関数が作れる!(bivarianceHack の正体) ❏ Playground で検証してみました 23
応用例 - Preact 24
Preactとは ❏ https://github.com/preactjs/preact ❏ Reactの軽量版としての再実装ライブラリ ❏ ReactからAPIを厳選している ❏ reconciliationの処理をフルスクラッチで書き直している ❏
一部の JSX の Transpiler 以外全て内製 ❏ React v17移行の jsx-runtime は Preact も同様に内製している ❏ babelのplugin/tscを用いることもReact同様に可能 ❏ JSX Pragma/JSX Factoryを h に書き換える 25
応用例 - React Three Fiber 26
React Three Fiberとは ❏ https://github.com/pmndrs/react-three-fiber ❏ React 向けの Three.js Renderer
❏ React JSX を Three.js の記法に変換している ❏ 変換の際に reconciliation も行っている ❏ react-reconciler の wrapper ❏ 内部で react-reconciler を呼び出している ❏ DOM ではなく Three.js の記法に1対1対応したJS オブジェクトを用いて fiber ツリーを作成 ❏ コードの解説 : https://codyb.co/articles/a-technical-breakdown-of-react-three-fiber 27
応用例 - Custom JSX Renderer 28
Custom JSX Renderer ❏ Render を自作するには前述の通り以下の方法で実現可能 ❏ JSX Pragma/JSX Factoryを設定し、独自の
createElement 関数を使う ❏ react-reconciler に独自の createElement 関数で生成した VDOM を渡す ❏ コアチームで開発中の OSS における取り組み ❏ Preact の手法に倣って Render を実装している ❏ コードベース(誰でも見られます) ❏ 実装の意図 : Editor.js の Plugin を JSX で記述出来るようにする ❏ 元は直接 DOM 操作を行うような JS の Class ❏ React Three Fiber の思想に倣って仮想 DOM と Class を1対1対応させている ❏ Reconciler は只今絶賛実装中です...(#times_hirai_shuta で経過が眺められます) 29
まとめ ❏ React の肝は react-reconciler ❏ 差分検出の仕組みが全てここに集約されている ❏ これを wrap
した OSS や、書き直した OSS が存在する ❏ 仮想 DOM などの一見とっつき難い言葉も仕組みを通せば理解出来る ❏ 一言で表現しにくいものに適当な名前をつけたに過ぎない場合がある ❏ とにかく仰々しい単語と思って必要以上にビビらなくて大丈夫です ❏ TypeScript の型システムは不健全 ❏ @types/react で悪用もとい活用されている ❏ 健全性について需要があればもう少し掘り下げて話します 30
ご清聴ありがとうございました 31