Slide 1

Slide 1 text

5分でわかる PreactのVDOMで作る Webエディタ did0es 2024/06/25 @ めぐろLT #16

Slide 2

Slide 2 text

did0es(Hirai Shuta) SWE @ CyberAgent, Inc. Main organizer @ Meguro.es 最近の供養したいこと: EURO2024 をリアタイ観戦して サッカー意識を高めていたところ 寝不足で怪我をしてしまい まさかの自分が負傷退場する羽目に 自己紹介

Slide 3

Slide 3 text

タイトル再掲 5分でわかる PreactのVDOMで作る Webエディタ

Slide 4

Slide 4 text

🤖 < エディタライブラリを使えば 5分もかからないのに...

Slide 5

Slide 5 text

車輪の再発明した結果 車輪ではないものを創り出してしまった お話です😇

Slide 6

Slide 6 text

背景 lexical(https://lexical.dev) を使いたかった ・Draft.js(https://draftjs.org)の後継 ・当時(2,3年前)はα版でdocsがスカスカだった α版を本番運用はできないので自作した ・メディアサイトの入稿画面を作る仕事の一貫 ・Reconciler を搭載したエディタライブラリを作れば  それはもう lexical では!?という安直な考え

Slide 7

Slide 7 text

エディタの要件 リッチ ・非エンジニアが使えるように ・DnDやGUIによるブロック操作は必須 特定のViewライブラリ非依存 ・React以外に、VueやWeb Componentsで組まれている箇所などでも  使えるように

Slide 8

Slide 8 text

どうやって何を作ったのか

Slide 9

Slide 9 text

実装フロー 1. lexical の実装を読む 2. React の技術の転用だと気づき、React の実装を読む 3. lexical, React の規模では再現できないと思い、よりミニマルな Preact の実装を読む 4. Preact から Reconciler を取り出す 5. Reconciler を好きなエディタライブラリに移植する 6. lexical かな それって lexical だね 差分検出大好き(完成🐲)

Slide 10

Slide 10 text

lexical の仕組みを簡単に 画像: https://dio.la/article/lexical-state-updates

Slide 11

Slide 11 text

🤖 < lexical の実装を 真似すればよかったのに...

Slide 12

Slide 12 text

人間は怠惰なので つい楽をしようとしてしまう

Slide 13

Slide 13 text

せや! 昔 React の中身を読んだことあったから その知識でどうにかしたろ!

Slide 14

Slide 14 text

lexical と似ている React を読んでみる https://github.com/facebook/react の Reconciler を中心に読みつつ、量が膨大 なので 以下の参考資料と併せて読んでいく ・https://ja.legacy.reactjs.org/docs/implementation-notes.html  ・旧型の差分検出(Stack)の話 ・https://jsconf.jp/2022/talk/internal-implementation-of-react  ・新型の差分検出(Fiber)の話 ・https://github.com/shuta13/react-deep-dive(注: 手前味噌)  ・Stack, Fiber 両方を再現する話

Slide 15

Slide 15 text

lexical より複雑では

Slide 16

Slide 16 text

Preact を読んでみる React の軽量版で、なんとコードは1000行程度(3年前の情報) https://github.com/preactjs/preact を読みつつ、適宜以下も参考に ・https://blog.ojisan.io/preact-reading  ・差分検出処理についてかなり詳細に書かれている記事 ・preactの仕組みを理解する軽量版教育用preactを作ってる話 - Speaker Deck  ・上の記事と同じ方がフルスクラッチで再現した話

Slide 17

Slide 17 text

Preact から Reconciler を取り出す preact/src/diff 配下の実装から、VDOM を比較・更新している処理だけを 取り出して動かす ・Preact は可読性よりも Perf を意識したコードになっているので  人間に優しいように、適宜処理の流れや変数名を書き換え ・そもそも元の実装は Pure JS なので TypeScript で書き換え

Slide 18

Slide 18 text

余談: react-reconciler をインストールすれば解決? react-reconciler というパッケージが React から独立して存在する ・これをインストールすれば差分検出できそう... ・しかし peerDeps に React が入っているのでスタンドアロンでは動かない ちなみに Preact は、reconciler などを個別にパッケージ化しない方針 ・react-three-fiber on Preact? (discussion) · Issue #2538

Slide 19

Slide 19 text

エディタライブラリへ移植 View ライブラリ非依存のエディタライブラリの選定 ・選ばれたのは Editor.js でした Editor.js ハック ・また内部実装を持ってくるわけにはいかないので  プラグインとして、Reconciler を入れる  ・プラグインを選択すると VDOM からブロックが生成される   ・ブロックごとに state を持つ   ・もはや lexical とは別物に...

Slide 20

Slide 20 text

デモ(時間あれば)

Slide 21

Slide 21 text

作ってみてどうだった?

Slide 22

Slide 22 text

よかった点 思いついたことを具現化できた ・アウトプット◯ ・発想△ lexical, React, Preactの実装に詳しくなった ・特に Preact を完全に理解した  ・VDOM から如何にして DOM を組み立てるのか  ・何の差分をどうやって検出するのか

Slide 23

Slide 23 text

苦労した点 Preact の hooks 周辺 ・内部状態を扱う箇所が副作用多めで難解 ・useState を中心に、自分が再現できるものだけ再現 型 ・元の実装は Pure JS だったので TS 化したが、工数が膨れ上がった  だけだった  ・一部で型の恩恵を得られたが ts-expect-error まみれ  ・Preact の処理をほぼそのまま動かせたのでテスト書くだけで十分だった

Slide 24

Slide 24 text

反省点 あまりにもオーバーエンジニアリング ・ラーメンを作るためにまず小麦を育てている状態 バグが生まれ続けた ・見事なマッチポンプが出来上がった ・この反省から別のライブラリを拡張した テストも元の実装から持ってくるべき ・今流行りのGoやRustによる置き換えはこれをやっている

Slide 25

Slide 25 text

https://github.com/cam-inc/pde.js (inactive) お賽銭代わりに良ければスターをポチッとお願いします😭

Slide 26

Slide 26 text

供養完了(?)

Slide 27

Slide 27 text

ご清聴 ありがとうございました!