大量のテキストを食っても速い Markdown Editor 作った
もう人生で何個目かわからない markdown エディタ作った。が、今回のは結構気に入っている。
https://markdown-buffer.netlify.com/ で遊べる。
用途としては、GitHub か Qiita か はてなブログかわからないが、なにか書こうと思ったときに、どのサービスも中途半端に重いので、とりあえずのバッファが必要、という感じで作った。なので速度重視。
ブラウザのストレージで永続化してる。オフラインで動く。できるだけエディタとしてはスコープを大きくせず、単に編集バッファ(textarea)でしかない、というのを意識している。
結構頑張って作り込んでしまった https://nedi.app が色々肥大化してしまっていて入力時にラグを感じるので、編集体験を見つめ直す自戒もある。
機能
- 数式対応
- コードハイライト対応
- バックグラウンドで自動保存
- 改行を br に(line-break)
- Desktop PWA 対応 (chrome://flags から有効化)
- Ctrl+Alt+F で Prettier
- Ctrl+1 で プレビューをトグル
- WordCount 機能
スクロールシンクを実装してない。厳密にやろうとすると面倒なので後回し。
off-the-main-thread
メインスレッドのパフォーマンスをかなり意識した。
たとえば、なぜ仮想DOMという概念が俺達の魂を震えさせるのか - Qiitaの markdown、8000字程度を remark でコンパイルするのに、メインスレッドで 23~40ms 掛かる。これは一文字打つたびに、実際にもたつきとして感じられる。
これを WebWorker に逃がすことで、メインスレッドで入力中は全くラグらなくなった。
DevToolsのフレームグラフみても全然負荷掛かってない。
その代り、postMessage が往復する時間で 4ms x 2 ぐらいのプレビューの遅延が発生した。0.5フレームなので人間が意識するのは難しい。
バックグラウンド側のスレッドの初期化がチョット重いのだが、これは prettier/standalone
のせいで、ただこいつを入れた結果ブラウザで prettier 使えるようになったので、まあいいかという感じ。もっとグレースフルに初期化する方法もあるが、そこはサボった。
使ったライブラリ
https://github.com/GoogleChromeLabs/comlink を使って postMessage をラップした。とても使いやすかった。
WebWorker 側だと localStorage に触れず、 IndexedDb を使う必要があったので、https://github.com/dfahlander/Dexie.js を使った。
remark の設定
このエディタでの書いたものを、外に持ち出したい場合の remark
import "github-markdown-css/github-markdown.css"; import "katex/dist/katex.min.css"; import "highlight.js/styles/default.css"; import remark from "remark"; import math from "remark-math"; import hljs from "remark-highlight.js"; import breaks from "remark-breaks"; import katex from "remark-html-katex"; import html from "remark-html"; const processor = remark() .use(breaks) .use(math) .use(katex) .use(hljs) .use(html); const html = processor.processSync("# Hello!).toString()