Slide 1

Slide 1 text

仮想DOMの仕組みを理解する 軽量版教育用 preact 〜俺の React、oreactを作った話〜 Yuta Ide (@sadnessOjisan) #new_style_study

Slide 2

Slide 2 text

自粛期間にしていたこと ❑ preact 読んでた https://blog.ojisan.io/preact-reading

Slide 3

Slide 3 text

preact とは ❑ 軽量版React, Reactのサブセット ❑ React と異なる実装だが、同一の機能・同一のインターフェースを 持つ ❑ 後発のライブラリであり、比較的読みやすい

Slide 4

Slide 4 text

2分でわかる preact

Slide 5

Slide 5 text

用語の整理 ❑ Element
hey
みたいなの ❑ Component ClasComponent, Functional Component. Element と区別しよう ❑ 仮想DOM DOMをJSのオブジェクトで表現したもの ❑ VNode preact における仮想DOMの表現 https://blog.ojisan.io/react-component-words

Slide 6

Slide 6 text

preact の責務 ❑ 仮想DOMからDOMツリーを構築 ❑ 新旧の仮想DOMを比較して差分をDOMに反映

Slide 7

Slide 7 text

Node Node Node Node Node Node diff(dom, newVNode, oldVNode)

Slide 8

Slide 8 text

主要な関数 diff 差分比較の起点。下記2つの関数を呼ぶ diffChildren Element + Component の VNode の 新旧children を比較して、DOM ツリーの追加・削除を行う。diff を再帰的に呼ぶ diffElementNodes Element の VNode の 新旧 props を比較して、DOM Node のプロパ ティを更新する。diffChildren を再帰的に呼ぶ

Slide 9

Slide 9 text

どのように diff が取られるか

Slide 10

Slide 10 text

Component Component Component Element Element Element Element Element props 更新

Slide 11

Slide 11 text

Component Component Component Element Element Element Element Element props 更新 diff 更新内容の newVNode が diff に渡されて呼ばれる

Slide 12

Slide 12 text

Component Component Component Element Element Element Element Element props 更新 diffChildren diff 子要素を持つコンポーネ ントなので、ツリー自体 に増減があるか確かめる

Slide 13

Slide 13 text

Component Component Component Element Element Element Element Element props 更新 diffChildren diff Element 子要素に対して diff を取る

Slide 14

Slide 14 text

Component Component Component Element Element Element Element Element props 更新 diffChildren diff Element diffElementNodes 子を持たないNodeに対して 、そのNode自体の値を更新 する

Slide 15

Slide 15 text

Component Component VNode Component Element Element Element Element Element props 更新 function diffChildren diff Element diffElementNodes diff を再帰的に呼ぶことで、 ツリーを深く辿ることができる

Slide 16

Slide 16 text

Props の更新で diff が発火する仕組み setState

Slide 17

Slide 17 text

setState renderComponent diff setState が呼ばれるとdiff が呼ばれるため 再レンダリングが起きる 次の状態をComponentの _nextStateに保存 diff を呼び出す _nextState を取り出す

Slide 18

Slide 18 text

setState renderComponent diff setState が呼ばれるとdiff が呼ばれるため 再レンダリングが起きる props が変わったら再レンダリング ↓ propsを監視しているわけではない!

Slide 19

Slide 19 text

setState が呼ぶ方法 lifecycle Eventハンドラからも呼び出せますが、preact成分は薄いので省きます

Slide 20

Slide 20 text

diff diffChildren diffElementNodes preact が diff中、diff後に実行してくれる commitRoot ライフサイクルの実行 renderQueueにライフサイ クルイベントの追加 renderQueueのイベントを 実行

Slide 21

Slide 21 text

preact とは ❑ 軽量版React, Reactのサブセット ❑ React と異なる実装だが、同一の機能・同一のインターフェースを 持つ ❑ 後発のライブラリであり、読みやすい

Slide 22

Slide 22 text

本当に読みやすい? ❑(比較的)読みやすい ❑ランタイムにおける最適化や行数の節約が意識されていたり、多少の 可読性は失われている ❑変数の再代入 ❑オブジェクトの破壊 ❑型が合わない ❑クラスを使わない ❑適当すぎる変数名 (i, j に Vnode を代入) ❑tmp にいろいろなもの渡して使いまわしてる ❑相互再帰 ❑条件節での代入 ❑条件節での副作用 ❑ For me 読みにくい!

Slide 23

Slide 23 text

というわけで、 読みやすい教育用 preact を作る

Slide 24

Slide 24 text

俺でも読める preact oreact https://github.com/sadnessOjisan/oreact

Slide 25

Slide 25 text

必要最低限の機能だけをサポート ❑ State ❑ Props ❑ ライフサイクル ❑ componentDidMount ❑ componentWillReceive ❑ componentWillUnMount ❑ スタイリング ❑ イベントハンドリング これだけあればなんでも(泥臭く) 作れる!! Let’s drilling props!

Slide 26

Slide 26 text

消した機能 ❑ Context ❑ Hooks ❑ Ref ❑ svg ❑ dangerouslySetInnerHTML ❑ setState への関数渡し ❑ 一部ライフサイクル ❑ SSRサポート

Slide 27

Slide 27 text

引数をオブジェクトで渡す ❑ 引数の数が多い ❑ 再帰的に呼ぶ関数がいくつかあり、どの状態になった引数が渡され るかを知りたい

Slide 28

Slide 28 text

型をつける ❑ 本家は JSDoc に型を書いている ❑ それをもとにTSで書き直す ❑ 型が合わない・・・ ❑ 一旦は後回しにしてドキュメントだけ充実させる

Slide 29

Slide 29 text

サンドボックスの作成 ❑ モノレポにした ❑ oreact を使ってアプリを作れるか確かめれる環境を作成 ❑ oreact 自体に console.log をしかけると、再帰的に呼ばれる diff の引数 を除き見れたりして挙動の理解がしやすい ❑ ライブラリ部分だけを publish もできる

Slide 30

Slide 30 text

https://sadnessojisan.github.io/oreact/

Slide 31

Slide 31 text

今後の目標 ❑ 変数の再代入を直したい ❑ 意味を持たない変数名に名前を適切な名前を与えたい ❑ 型を合わせたい これに対応しようとすると、結局は書き直しに なりそう。書き直したものは preact と呼べる のか? 本当の意味で 俺の react になりそう