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
Webエディタライブラリ 「CodeMirror」から学ぶ Webアプリ開発のテクニック
Search
igarashi
July 07, 2024
Programming
0
420
Webエディタライブラリ 「CodeMirror」から学ぶ Webアプリ開発のテクニック
2024/07/05に開催されたDevelopersIO 2024 SAPPOROにて登壇したセッションの資料です。
igarashi
July 07, 2024
Tweet
Share
More Decks by igarashi
See All by igarashi
Zennのパフォーマンスモニタリングでやっていること
ryosukeigarashi
0
140
Other Decks in Programming
See All in Programming
アジャイルを支えるテストアーキテクチャ設計/Test Architecting for Agile
goyoki
9
3.3k
CSC509 Lecture 12
javiergs
PRO
0
160
CSC509 Lecture 09
javiergs
PRO
0
140
PHP でアセンブリ言語のように書く技術
memory1994
PRO
1
170
Duckdb-Wasmでローカルダッシュボードを作ってみた
nkforwork
0
130
RubyLSPのマルチバイト文字対応
notfounds
0
120
Compose 1.7のTextFieldはPOBox Plusで日本語変換できない
tomoya0x00
0
190
Jakarta EE meets AI
ivargrimstad
0
650
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
1
100
とにかくAWS GameDay!AWSは世界の共通言語! / Anyway, AWS GameDay! AWS is the world's lingua franca!
seike460
PRO
1
890
[Do iOS '24] Ship your app on a Friday...and enjoy your weekend!
polpielladev
0
110
카카오페이는 어떻게 수천만 결제를 처리할까? 우아한 결제 분산락 노하우
kakao
PRO
0
110
Featured
See All Featured
It's Worth the Effort
3n
183
27k
Navigating Team Friction
lara
183
14k
Docker and Python
trallard
40
3.1k
Building Your Own Lightsaber
phodgson
103
6.1k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
329
21k
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.2k
Designing for Performance
lara
604
68k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
YesSQL, Process and Tooling at Scale
rocio
169
14k
5 minutes of I Can Smell Your CMS
philhawksworth
202
19k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
What's in a price? How to price your products and services
michaelherold
243
12k
Transcript
Webエディタライブラリ 「CodeMirror」から学ぶ Webアプリ開発のテクニック 2024.7.5 新規事業部 Zennチーム Igarashi
Xへの投稿の際は、 ハッシュタグ #devio2024 でお願いいたします。 2 お願い
Igarashi Ryosuke • 2015/7⼊社 • CX事業本部(旧モバイルアプリサービス 部)でバックエンド‧インフラを担当 • 2021/6より新規事業部 Zennチーム
• フロントエンドもやってますが何もわから ない ⾃⼰紹介 3
はじめに 4
とは Zennは「知見を共有するエンジニアに対価を」 というコンセプトでつくられた 技術情報共有コミュニティです。 5
3種類の投稿形式で、その時々に合った粒度で知見を残すことができます ひとまず 雑にメモ したい あのテーマ で誰かと 議論したい 最近学んだ あの話を記事 にしよう
労力が かかった分 有料で販売 しよう あの話を まとめて 本にしよう 6
著者が金銭的な対価を受け取れる仕組み 知見をまとめて 有料の本として 販売してみよう 応援したい 著者には 有料のバッジ を贈ろう バッジを受け取った著者に 分配金が支払われます
7
8 8
catnose さんが個人プロジェクトとしてリリース 運営会社がクラスメソッド株式会社に 2020年9月 2021年6月 5人の小さなチームで運営中 現在 のこれまで 9 企業運営になってからも自分たちがワクワクすることに積極的に取り組むスタンスは変わって
いません。ほぼすべての意思決定はチームメンバーだけで行われており、メンバー一人ひとり のアウトプットがサービスの質に直結します。
本編 10
最近のエディタ周りのアップデート 11
ZennのMarkdownエディタの作り⽅ アップデートで⾏ったことはほとんどすべて「Zenn Tech Blog」で公開しています。 12
お話すること CodeMirrorの実装からわたしが学んだこと‧興味深 かったこと伝えします。 🚀 パフォーマンス最適化 🚀 状態管理のアーキテクチャ 🚀 拡張性 13
CodeMirrorの実装からわたしが学んだこと‧興味深 かったこと伝えします。 🚀 パフォーマンス最適化 🚀 状態管理のアーキテクチャ 🚀 拡張性 収まりきらなかったので記事として書きます
お話すること 14
注意‧免責事項 • 本スライドの内容はCodeMirrorのドキュメント やソースコードを参考に作成していますが、正確 ではない可能性があります。 • 本スライドの内容はCodeMirror v6に関する内容 です。v6はv5以前とは実装が全く異なりますので ご注意ください。
15
ZennのエディタとCodeMirror 16
ZennのMarkdownエディタ ZennのMarkdownエディタはCodeMirrorというライ ブラリをベースに、多数のカスタマイズを加えてい ます。 17
ZennのMarkdownエディタ 18
ZennのMarkdownエディタ 19 Markdown記法の デコレーション URLをペーストで自動 的にリンク生成 画像をD&Dでアップ ロード・リンク生成 ショートカットキーによる Markdown記法の挿入
(太字・斜体など) SlackライクなEmojiの 入力補完
CodeMirrorとは “CodeMirrorは、Web⽤のコードエディターコン ポーネントです。多くの編集機能をサポートするテ キスト⼊⼒フィールドを実装でき、さらなる拡張を 可能にする豊富なプログラミング インターフェイス を備えています。”(翻訳) 20 引用: https://codemirror.net/
Features 21 - Modularity - Speed - Bracket Closing -
Linting - Flexible Styling - Theming - Collaborative Editing - Undo History - Multiple Selections - Internationalization ...and more - Accessibility - Mobile Support - Bidirectional Text - Syntax Highlighting - Line Numbers - Autocompletion - Code Folding - Search/Replace - Full Parsing - Extension Interface
Language Support 公式がサポートする⾔語。 この他に、コミュニティが作成した⾔語サポートも あります。 22
ちなみに ProseMirrorという、Notionライクなブロック ベースのエディタライブラリもあります。 ラッパーライブラリとして や などが有名です。 作者はCodeMirrorとおなじ⽅です。 23
ブロックエディタのトレードオフ 良いところ • プレビュー不要 • リッチな表現をUIで実現できる ⼤変なところ • 編集‧表⽰の2つのモードの実装が必要 •
細かい挙動の調整 24
質問✋ 技術記事を書く時に使いたいエディタはどっち? (A)Markdownベースの「テキストエディター」 (B)Notionライクな「ブロックエディター」 25
🚀パフォーマンス最適化 26
基礎知識 27 このテキストエディタのHTMLはどのようになって いるでしょうか?
基礎知識 28 contenteditable=”true”により、 divやspanのテキストが編集可能に 1⾏⽬ 2⾏⽬ 3⾏⽬ class指定による ハイライトの装飾
仮想スクロール ⼤量のデータをブラウザにレンダリングする際に、可視範囲 のDOMだけを動的に⽣成することで、レンダリングにかかる 時間を⼩さくしてパフォーマンスを向上させるテクニック。 動的な変数をもとにレイアウト(描画範囲)を決定する。 • エディタの⾼さ • 1⾏あたりの⾼さ •
スクロール位置 • その他 29
仮想スクロール 30 例えばこんなCSS div.outer { height: 500px; overflow: auto; }
div.inner { height: 10000px; }
仮想スクロール トレードオフ • DOMが⽣成されていない部分はブラウザ検索が 効かない(別途実装が必要) • など 31
レイアウト計測はコストが⼤きい テキストの⽂法解析 ↓ テキストを構造化 ↓ テキストのデコレーションや様々な状態を適⽤ ↓ ようやくレイアウトが計測できる 32
レイアウト計測はコストが⼤きい 変数が変わるたびに1フレーム内で何度もレイアウ ト計測を実⾏してしまうとフレーム落ちが発⽣する 👉 requestAnimationFrameを使う 33
requestAnimationFrameとは CSSなどでは表現が難しいアニメーションを、 JavaScriptからブラウザのリフレッシュレートにあ わせてスムーズに描画するためのAPIです。 34
ブラウザのレンダリングサイクル • ブラウザはMainスレッドでレ ンダリングを⾏う • 初回は全部通りますが、2回 ⽬以降は差分更新 • 余った時間でクライアント JavaScriptの実⾏も⾏う
35 https://web.dev/learn/performance/understanding-the-critical-path?hl=ja
フレーム落ちとは • 処理時間が⻑いJavaScriptがあると、レンダリン グタイミングが数フレームに1回になる。 • 50ms以上かかるタスクは分割したほうが良いと されています。 36 https://web.dev/articles/long-tasks-devtools?hl=ja
フレーム落ちとは • requestAnimationFrameを使うことで、処理を フレームの先頭に先送りする。 37
requestAnimationFrameの例 アニメーションの場合、 コールバック関数の中で 再帰呼び出しをして、差 分時間から移動距離を算 出する 38 引用: https://developer.mozilla.org/ja/docs/Web/API/windo w/requestAnimationFrame
再帰的に呼び出し 呼び出された時間 開始からの経過時間 時間から移動距離を測る
requestAnimationFrameの例 39 フレームごとにrequestAnimationFrameの コールバックが実行される
CodeMirrorの場合 エディタの状態が更新された時 • テキストのDOM更新は即座に⾏う。 • レイアウト計測はrequestAnimationFrameで次 のフレームの先頭で⾏い、仮想スクロールを更新 40 引用: https://github.com/codemirror/view/blob/6.28.4/src/editorview.ts#L67-L72
ハイライトもコストが⼤きい テキストの⽂法解析 ↓ テキストを構造化 ↓ テキストの選択範囲や様々な状態を反映 41
ハイライトもコストが⼤きい これらをDOM更新と同じタイミングで実⾏するとコ ストが⼤きいのでフレーム落ちが発⽣する可能性が ある。 👉 setTimeout/requestIdleCallbackを使う 42
setTimeoutとは 指定した時間が経過した後にコールバックを実⾏す るAPIです。 ブラウザ環境においては、setTimeoutの待ち時間の 間、ブラウザの処理を実⾏することができる。 43
requestIdleCallbackとは ブラウザのスレッドがアイドル状態のときに実⾏さ れる関数をキューイングできます。優先度が低くコ ストが⼤きい処理をさせるのに有効です。 44
requestIdleCallbackとは 45 ただし、Safariはまだ⾮対応です。
CodeMirrorの場合 requestIdleCallbackが⾮対応環境 • setTimeoutで500ms遅延 requestIdleCallbackが対応環境 • setTimeoutで100ms遅延 • requestIdleCallbackで0~400ms遅延 46
CodeMirrorの場合 47 IdleCallbackで解析 レイアウト 計測して レンダリン グ 大量のコード をペースト 100ms
まとめ 48 • 仮想スクロールは⼤量のデータをパフォーマンス を落とすことなくレンダリングするテクニック。 • レンダリングコストが⼤きい処理はブラウザに⽤ 意されたAPIを⽤いて遅延実⾏させることでフ レーム落ちを抑える。 ◦
requestAnimationFrame ◦ setTimeout ◦ requestIdleCallback
おわりに 49
おわりに • CodeMirrorの実装から学んだ、広く活⽤できそ うな知識‧テクニックをお話しました。 • なにかのお役に⽴てれば幸いです。 • 素晴らしいライブラリと作者に感謝します。 50
None
52