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

Technologies for developing editors / Webエディタ開発を支える技術

did0es
January 19, 2023

Technologies for developing editors / Webエディタ開発を支える技術

MuddyWeb #4 19:00 - 19:20「Webエディタ開発を支える技術」の資料です。

株式会社CAMがOSSとして開発を行っているpde.js( https://github.com/cam-inc/pde.js )について、生まれた背景や内部実装、これを用いたWebエディタ開発などのmuddyな部分をお話します。

Speaker: Hirai Shuta( @did0es: https://twitter.com/did0es )
Event URL: https://cyberagent.connpass.com/event/270629/

did0es

January 19, 2023
Tweet

More Decks by did0es

Other Decks in Technology

Transcript

  1. Webエディタ開発を 支える技術 Muddy Web #4 Speaker: Hirai Shuta 2023 /

    01.19
  2. 平井 柊太(ひらい しゅうた) 2022年度 新卒入社 株式会社CAM Webフロントエンドエンジニア Twitter: did0es /

    GitHub: shuta13
  3. はじめに

  4. お話すること • 何を解決するのか • どのように解決するのか • 振り返り • 今後の展望 •

    まとめ
  5. エディタ →

  6. エディタ →コンピュータ上で各種オブジェクトを編集する  ソフトウェア

  7. Webエディタ →

  8. Webエディタ →Webブラウザで使用するエディタ

  9. VSCode エディタの例

  10. VSCode Wordpress (Gutenberg) エディタの例

  11. VSCode Wordpress (Gutenberg) Notion エディタの例

  12. VSCode Wordpress (Gutenberg) Notion

  13. VSCode Wordpress (Gutenberg) Notion テキストエディタ ブロックエディタ

  14. これらのようなブロックエディタを実装するお話です。 Wordpress (Gutenberg) Notion

  15. 使用技術の紹介 Editor.js

  16. Editor.jsとは • 豊富なプラグイン • 独自のプラグインも実装可能 • (ある程度)クリーンデータ • UIライブラリ非依存

  17. Editor.jsとは • 豊富なプラグイン • 独自のプラグインも実装可能 • (ある程度)クリーンデータ • UIライブラリ非依存 機能性・拡張性の高いブロックエディタを

    UIライブラリ無しで実装できるライブラリ
  18. Editor.jsとは • 豊富なプラグイン • 独自のプラグインも実装可能 • (ある程度)クリーンデータ • UIライブラリ非依存 機能性・拡張性の高いブロックエディタを

    UIライブラリ無しで実装できるライブラリ
  19. Editor.jsプラグイン

  20. Editor.jsプラグイン 赤枠内全て

  21. Editor.jsプラグインの名称と機能 Block Tool Inline Tool Block Tune

  22. Editor.jsプラグインの名称と機能 Block Tool →ブロック作成機能 Inline Tool →テキスト編集機能 Block Tune →ブロック編集機能

  23. 何を解決するのか

  24. Editor.jsプラグイン実装

  25. Editor.jsプラグイン実装 1.特定のメソッドを含む Classを作成

  26. Editor.jsプラグイン実装 2.Editor.jsにClassを 渡す 1.特定のメソッドを含む Classを作成

  27. Block ToolのメソッドとUI

  28. Block ToolのメソッドとUI

  29. Block ToolのメソッドとUI

  30. プラグイン実装に潜む課題

  31. DOMツリー → JSON(JSのObject) → プラグイン実装に潜む課題

  32. DOMツリー →命令的なUIの記述 JSON(JSのObject) →宣言的なUIの記述 プラグイン実装に潜む課題

  33. プラグイン実装に潜む課題 DOMツリー →命令的なUIの記述 JSON(JSのObject) →宣言的なUIの記述 UIを宣言的に書きたい

  34. Editor.jsプラグイン実装の課題と問題 • 書き方にばらつきがある ◦ 宣言的な記述と命令的な記述が混在している • 命令的な記述はコードの維持が難しい ◦ 可読性が下がりがち ◦

    コードの実行順から UI の状態を推測しづらい ◦ データ変更のタイミングが分かりづらい • データの管理が難しい ◦ エディタはデータの入出力が多い ◦ HTMLのデータ属性にこのデータを詰め込みたくない(...ですよね?)
  35. 課題と問題に対する解決アプローチ • 書き方にばらつきがある ◦ 宣言的な記述と命令的な記述が混在している • 命令的な記述はコードの維持が難しい ◦ 可読性が下がりがち ◦

    コードの実行順から UI の状態を推測しづらい ◦ データ変更のタイミングが分かりづらい • データの管理が難しい ◦ エディタはデータの入出力が多い ◦ HTMLのデータ属性にこのデータを詰め込みたくない(...ですよね?)
  36. 課題と問題に対する解決アプローチ • 書き方にばらつきがある ◦ 宣言的な記述と命令的な記述が混在している • 命令的な記述はコードの維持が難しい ◦ 可読性が下がりがち ◦

    コードの実行順から UI の状態を推測しづらい ◦ データ変更のタイミングが分かりづらい • データの管理が難しい ◦ エディタはデータの入出力が多い ◦ HTMLのデータ属性にこのデータを詰め込みたくない(...ですよね?) 宣言的に書けるような 記法を提供する データ管理向けの 仕組みを提供する
  37. どのように解決するのか

  38. ゴール1. Editor.jsプラグインを宣言的に実装できる ゴール2. プラグインのデータ(状態)管理ができる ゴール3. 本来のインターフェースとかけ離れていない

  39. Editor.jsとは • 豊富なプラグイン • 独自のプラグインも実装可能 • (ある程度)クリーンデータ • UIライブラリ非依存

  40. Editor.jsとは • 豊富なプラグイン • 独自のプラグインも実装可能 • (ある程度)クリーンデータ • UIライブラリ非依存 これらの特性も活かすように実装する

  41. 理想(プラグイン実装時)

  42. 理想(プラグイン実装時)

  43. 理想(プラグイン実装時)

  44. 理想(プラグイン実装時)(+α)

  45. 理想(プラグイン使用時)

  46. ゴール1. Editor.jsプラグインを宣言的に実装できる ゴール2. プラグインのデータ(状態)管理ができる ゴール3. 本来のインターフェースとかけ離れていない ✅

  47. 実装したもの =

  48. 実装したもの = Reactに依存しない、Reactっぽく書ける  Editor.jsプラグイン実装向けライブラリ

  49. None
  50. Editor.jsとは • 豊富なプラグイン • 独自のプラグインも実装可能 • (ある程度)クリーンデータ • UIライブラリ非依存

  51. Editor.jsとは • 豊富なプラグイン • 独自のプラグインも実装可能 • (ある程度)クリーンデータ • UIライブラリ非依存 特にこの特性を潰したくなかった

  52. None
  53. 手順 • JSX Factoryの定義 • 差分検出処理の導入 • 状態管理を実現する

  54. JSX Factoryとは JSXをJSに変換すると生成される 関数のこと。 @babel/preset-reactを用いて 変換すると右の画像のようになる。 React.createElementの部分が JSX Factoryに該当する。

  55. 独自のJSX Factoryを使う コンパイラの設定を変えると 独自(=React.createElement以外)の JSX Factoryを使える。 babelであればpragmaを typescriptであればjsxFactoryを それぞれ設定する。 ファイル内に/*

    @jsx */コメントを 書くことでも設定可能。
  56. 独自のJSX Factoryを使う

  57. 独自のJSX Factoryを使う /* @jsx myJsxFactory */

  58. 独自のJSX Factoryを使う /* @jsx myJsxFactory */

  59. 独自のJSX Factoryを使う /* @jsx myJsxFactory */ myJsxFactoryを実装すれば 任意の処理を適用しながらJSX要素を探索できる

  60. (当資料における)差分検出処理とは 2つの木の前後を比較し差分を取る 処理のこと (木 = JSX要素ツリー) JSX FactoryではJSX要素ツリーを 差分を検出しやすい形に変換して返す。 (差分を検出しやすい形

    = JSON) ※イメージ
  61. 差分検出処理を導入するにあたっての課題 当初はReactと同じ方法(react-reconciler) で差分を検出する予定だった。 ...が、react-reconcilerはreactに依存する。 react依存の部分を剥がし、差分検出処理のみ スタンドアロンで利用出来るように試みた。 ...が、コード量が膨大で誰も把握・メンテ できないことを懸念し、他の方法を模索した。

  62. Preactで代用して解決 Preactの差分検出の仕組みを 移植(書き換え)することで解決した。 Preactの差分検出は1000行[※]程度の ミニマルなコードで記述されている。 (※ ライブラリ作成当初。参考) Reactよりもコードの全容が把握しやすく メンテできる。

  63. とりあえずJSXで書けるようになった

  64. 状態管理 PreactのHooksを参考に実装。 useStateやuseReducerで状態を作成し 更新用関数を取得する。 useWatchやuseMountで副作用を管理する。

  65. https://github.com/cam-inc/pde.js 完成したもの

  66. None
  67. Playground CodeSandboxで色々試してみてください。

  68. Docs https://cam-inc.github.io/pde.js

  69. ライセンス • pde.js: Apache-2.0 License ◦ ライセンス ◦ Editor.jsのサブセットとして、Editor.jsのライセンスに倣った •

    Preact: MIT License ◦ Preactをインストールしないので、自前で記載が必要。 ◦ Preactのオリジナルのライセンス文と、そのリンクをコメントで挿入。 ◦ sourcemapとして書き出して配信。
  70. 振り返り

  71. まとめ・所感 • Webエディタ開発で感じた課題を技術で解決した ◦ 宣言的なUIの記述でEditor.jsプラグインを書けるようになった ◦ ただ、未だ型やEditor.jsと接続する部分でバグが多い • PreactやReactの差分検出処理に対する理解を深められた ◦

    JSX要素ツリーの比較 ◦ Hooks • 先人と技術へのリスペクトを忘れない ◦ Editor.jsやPreactを作った先人に感謝
  72. 今後の展望

  73. Coming Soon... Slate.js + Reactによる 更に質の高いブロックエディタ実装向けライブラリ(OSS)を開発中

  74. おわりに

  75. https://cam-inc.co.jp/p/techblog/710053497071993899 今回お話した内容はこちらからもご覧になれます

  76. https://github.com/cam-inc/pde.js ご興味あればコントリビュートお待ちしております!

  77. ご清聴ありがとうございました。

  78. Webエディタ開発を 支える技術 Muddy Web #4 Speaker: Hirai Shuta 2023 /

    01.19