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

Building markdown editor using Rust’s parser

Building markdown editor using Rust’s parser

HiroyukiYagihashi

November 27, 2021
Tweet

More Decks by HiroyukiYagihashi

Other Decks in Technology

Transcript

  1. 本セッションで話すこと - 作ったもの - アーキテクチャ - アーキテクチャのモチベーション - フロントエンド複雑化の流れ -

    問題点 - 解決策 - 実装の紹介 - Rustのライブラリをwasm pkg化する - wasm pkgをdependenciesに追加する - wasm pkgをロードするReact Hookを定義する - 定義したReact Hookを呼び出す - まとめ
  2. https://editor.yagipy.me - 3種類のプレビュー形式に対応 - デフォルト - マインドマップ - スライド -

    3種類のレイアウトに対応 - 2カラム(textarea,preview) - textareaのみ - Previewのみ - 本セッションでは、デフォルト/スライドで使用しているRustコード(マー クダウンパーサー)をReactで使用するまでのアーキテクチャを紹介します
  3. 前提: フロントエンド大規模化の流れ - ロジックがフロントエンドに寄ってきている - 主なメリット: 無駄な通信の削減、サーバーリソースの削減 - よりユーザーの近くで計算した方が良い -

    エッジコンピューティングやフォグコンピューティングの流れ - サーバーに戻そう、という動きもあるにはあるが ...(React Server Components等)
  4. 解決策 - 色々ある - blitz, Kotlin Multiplatform, wasm, etc.. -

    様々な言語の資産を活用したい場合はwasmが選択肢に入る - 今回は、実験としてRustのコードをwasmにしてWeb上で使用するという実 装を行った
  5. 1. Rustのコードをwasm pkg化する 2. wasm pkgをdependenciesに追加する 3. wasm pkgをロードするReact Hookを定義する

    4. 定義したReact Hookを呼び出す RustコードをReactアプリで使用するまでの手順
  6. Rustのコードをwasm pkg化する - wasm-packを使用 - wasm_bindgen + package.json等を出力(npm publishする場合にスムーズに対応でき る)

    - wasm_bindgen: #[wasm_bindgen]アトリビュートを付けた関数の wasmとJavaScript のラッパーとTypeScriptの型定義を生成する - https://developer.mozilla.org/ja/docs/WebAssembly/Rust_to_wasm#buildi ng_the_package use pulldown_cmark::{html, Options, Parser}; use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn pulldown_cmark(source_text: &str) -> String { // ~~~ 省略 ~~~ html_output }
  7. wasm pkgをロードするReact Hookを定義する - wasmを含んだJavaScriptは動的に読み込む必要があるので、その読み込み を待ってrerenderする import { pulldown_cmark }

    from 'markdown-parser' export interface IPullDownCmark { pulldown_cmark: typeof pulldown_cmark } export const usePullDownCmark = () => { const [state, setState] = useState<IPullDownCmark | null>(null) useEffect(() => { (async () => { const wasmContainer = await import('markdown-parser') setState(wasmContainer) })() }, []) return state }
  8. 定義したReact Hookを呼び出す - 作成したHookを呼ぶ - wasm_bindgenした関数が呼べる interface IProps { text:

    string } export const DefaultPreview = ({ text }: IProps): ReactElement => { const instance = usePullDownCmark() return ( <div dangerouslySetInnerHTML={{ __html: instance?.pulldown_cmark(text) ?? '', }} /> ) }