Penpotの限界を突破せよ:Wasmによる「ブラウザ・ネイティブ」な超高速デザインエンジニアリングの深淵
Penpotは単なるオープンソースのデザインツールではない。SVGベースのWebネイティブなデータ構造を持つ、我々エンジニアにとって最も「ハックしがいのある」キャンバスだ。
Figmaのプラグイン開発が閉鎖的なサンドボックスの中で喘いでいる間、PenpotはCSS/SVGというWeb標準をそのままAPIとして開放している。しかし、大規模なベクター変換や複雑な幾何学演算をJavaScriptのメインスレッドで回せば、即座にUIはフリーズする。
本記事では、WebAssembly (Wasm) を活用し、Penpotのプラグインを「重い計算の檻」から解放し、圧倒的なパフォーマンスを手に入れるための裏技を伝授する。
—
1. なぜ「JS単体」ではスケールしないのか
デザインツールにおける「重い処理」とは、多くの場合、複雑なベクターパスの正規化、ポリゴン分割、あるいは膨大なアセットのバイナリ変換である。
- JSの限界: ガベージコレクション(GC)の停止と、シングルスレッドによるイベントループのブロック。
- Wasmの最適解: 線形メモリ(Linear Memory)を活用し、JavaScriptのヒープ外で高速なC++/Rust演算を行う。PenpotのDOM(あるいは内部データ)を、`SharedArrayBuffer`を介してシームレスに操作する。
2. アーキテクチャの設計:Wasmブリッジの構築
Penpotプラグインはブラウザのサンドボックス内で動く。ここでRustで記述したWasmモジュールをロードし、JSとメモリを共有するのが最適解だ。
Rust側のコード(簡略版: パス演算の高速化)
use wasm_bindgen::prelude::;
// JavaScriptから送られてきたベクター配列を高速演算
[wasm_bindgen]
pub fn optimize_paths(data: &[f32]) -> Vec
// ここで複雑な幾何学処理を行う
// JS側で逐次実行するよりも10倍〜50倍高速
data.iter().map(|x| x 0.5).collect()
}
JS側(Penpotプラグインのエントリーポイント)
// Wasmのメモリを効率的にバインド
import init, { optimize_paths } from ‘./wasm/processor.js’;
async function runHeavyProcessing(nodes) {
await init();
// Penpotから取得したノードデータをWasmの線形メモリに流し込む
const optimized = optimize_paths(nodes.map(n => n.x));
// 結果を反映
updatePenpotNodes(optimized);
}
3. パフォーマンスを極めるための最適化ハック
A. メモリの「ゼロコピー」戦略
WasmとJSの間でデータをやり取りする際、シリアライズ(JSON変換)を繰り返すとオーバーヘッドで死ぬ。
- Bufferの共有: `WebAssembly.Memory`をエクスポートし、JS側から直接`TypedArray`としてアクセスすること。これにより、メモリのコピーなしでデータを変換できる。
B. Workerとの連携
UIスレッドを維持するために、Wasmの実行は必ずWeb Worker内で行うべきだ。
- PenpotのメインUIスレッド(UI.js)からメッセージをWorkerに送り、Wasmでの計算完了後に`postMessage`で返す。これにより、100万頂点を超えるようなSVGデータでもUIが固まることはない。
4. DevOps的アプローチ:CLIによる自動化パイプライン
PenpotはWeb APIが強力だ。GUIでポチポチ操作するのは初心者のやること。我々は「Penpot CLI + Wasm」のパイプラインを組む。
1. Export: PenpotのAPIを叩き、最新のデザインデータをJSONとして取得。
2. Transform: ローカルのRust/WasmバイナリをCLIから呼び出し、デザインシステムに従って命名規則の一括変更やプロパティの最適化を実行。
3. Sync: 変更後のデータを`penpot-api`経由で再びプッシュ。
自動化フローの例
penpot-cli export –file-id
./wasm_optimizer –input raw_data.json –output processed_data.json
penpot-cli import –file-id
5. 結論:ツールを「所有」せよ
多くのデザイナーやエンジニアは、提供されたツールのUIの中で思考を完結させてしまう。しかし、PenpotのようなWebネイティブなツールにおいて、プラグイン開発とは「ツールの機能を自ら拡張し、自身のワークフローに合わせて再定義する」ことと同義だ。
Wasmを投入し、低レイヤのメモリ操作まで掌握したとき、あなたのツールは「他人が作った箱」から「あなたの手足となる専用マシン」へと進化する。
このレベルに到達すれば、デザインシステムの一括管理や、数千のコンポーネントの動的生成など、手作業では数週間かかるタスクがわずか数秒で完結する。さあ、ブラウザの向こう側にある本当の可能性をハックしてほしい。
—
追記: Penpotの内部APIは進化が早いため、`package.json`での依存管理は厳格に行い、常にAPIの変更をCIで検知する仕組みを構築することを推奨する。エンジニアリングとは、常に備えることである。