Upgrade to Pro — share decks privately, control downloads, hide ads and more …

preactの仕組みを理解する軽量版教育用preactを作ってる話

sadnessOjisan
November 05, 2020

 preactの仕組みを理解する軽量版教育用preactを作ってる話

preact を読みやすいように色々削りました

sadnessOjisan

November 05, 2020
Tweet

More Decks by sadnessOjisan

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

  4. 2分でわかる preact

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  10. Component
    Component
    Component
    Element Element
    Element
    Element
    Element
    props
    更新

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. setState renderComponent diff
    setState が呼ばれるとdiff が呼ばれるため
    再レンダリングが起きる
    props が変わったら再レンダリング

    propsを監視しているわけではない!

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide