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
did0es
November 01, 2024
Technology
21
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
780
ブラウザの投機的読み込みと投機ルールAPIを理解し、Webサービスのパフォーマンスを最適化する
shuta13
3
340
うわっ...私のSwagger、古すぎ...?grpc-gateway向けのSwaggerと向き合う
shuta13
0
160
ViteとTypeScriptのProject Referencesで 大規模モノレポのUIカタログのリリースサイクルを高速化する
shuta13
3
370
歴代のWeb Speed Hackathonの出題から考えるデグレしないパフォーマンス改善
shuta13
8
870
なぜクラウドサービスで 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
はてなのサービス基盤を支える Kubernetes《足腰》
masayoshimaezawa
0
390
Foundry Toolkit + Lemonade Serverでローカルワークフロー開発
seosoft
0
110
AIで政治は変わるのか? — 中高生と考えたAI時代の民主主義(東海高校サタデープログラム)
eitarosuda
0
340
組織における AI-DLC 実践
askul
0
260
背中から、背中へ /paying forward to community
naitosatoshi
0
200
フロントエンドイチゲキ実装 ― Figmaデザインと画面設計書からAIに実装・テストを書かせるための”下ごしらえ” / 20260627 Yusuke Mazuka
shift_evolve
PRO
0
120
AIDLC_ヤフーショッピングの取り組み
lycorptech_jp
PRO
0
340
AIをフル活用してオンコール機能のプロトタイプを2日で作った話 / Building an AI-Powered On-Call Prototype in Just Two Days
nari_ex
0
160
ご挨拶「10周年を迎える共創ラボのこれまでとこれから」
iotcomjpadmin
0
170
4人目のSREはAgent
tanimuyk
0
350
5分でわかる Amazon Connect_20260608
hwangbyeonghun
0
160
『AIに負けない』より『AIと遊ぶ』」〜ワクワクが最強のテスト・QA学習戦略_公開用
odan611
1
320
Featured
See All Featured
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
270
VelocityConf: Rendering Performance Case Studies
addyosmani
333
25k
Deep Space Network (abreviated)
tonyrice
0
220
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
550
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.6k
Agile that works and the tools we love
rasmusluckow
331
22k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
270
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Color Theory Basics | Prateek | Gurzu
gurzu
0
380
Site-Speed That Sticks
csswizardry
13
1.2k
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