Figmaプラグインのメインコードと、showUIで開くHTML画面は、使えるAPIが異なります。ブラウザー用のコードをそのままメイン側へ貼ると、DOM操作や保存処理などが動かないことがあります。ここでは開発入門の次に確認する実装上の注意点を整理します。
メインコードとUIの役割を分ける
| 処理 | 担当 |
|---|---|
| ノード・スタイルの取得や変更 | メインコードのfigma API |
| HTMLの入力欄、Blob、ダウンロード | UIのiframe |
| 双方のデータの受け渡し | figma.ui.postMessageとpluginMessage |
| 設定の永続保存 | 用途に応じてclientStorageやpluginDataを選ぶ |
ノードオブジェクトをUIへそのまま渡さず、ID・名前など必要な値に変換します。UI側のmessageはparentからのものか確認し、メイン側でもtypeと値を確認します。表示する名前はtextContentなどを使い、任意のレイヤー名をHTMLとして挿入しません。
出典:How Plugins Run、figmaのUIとclientStorage。
dynamic-pageでは非同期APIを使う
新しいmanifestのdocumentAccessはdynamic-pageを前提にします。getNodeByIdAsync、getMainComponentAsync、getLocalPaintStylesAsyncなどをawaitし、nullや拒否を処理します。同期版の名前を非同期版へ変えるだけでなく、呼び出す関数とその利用側もasync/awaitにします。
全ページが必要でなければ現在のページを対象にします。loadAllPagesAsyncは大きなファイルで時間がかかるため、必要な処理でのみ使います。ページを切り替える場合はsetCurrentPageAsyncを使います。
出典:figma API、InstanceNode、Plugin Manifest。
readonly・mixed・IDの違いを確認する
selectionは配列を直接pushして変更する対象ではありません。新しい配列を作ってfigma.currentPage.selectionへ代入します。figma.mixedは複数値を示す特殊な値なので、色や文字列と同じ処理へ渡す前に判定します。
ノードIDはファイル内の対象を指定するために使い、コンポーネントキーはライブラリの参照に使います。UIのnode-id=12-34とPlugin APIの12:34の表記も区別します。IDの末尾を理由なく削ると別の対象になるため、必要な表記変換以外は行いません。
テキストを変える前にフォントを読み込む
文字や文字サイズなど表示に関わる変更ではloadFontAsyncが必要です。混在フォントを1つのfontNameとして渡すのではなく、変更範囲のフォントを調べます。フォントがない場合の対処を決め、失敗を成功として数えません。
出典:フォント読み込みAPI。
並列実行と分割実行を使い分ける
独立した少数の取得はPromise.allでまとめられます。一方、大量のノードへ無制限にPromiseを作ると負荷が増えます。件数を区切り、適切な間隔で進行状況をUIへ送ります。Promise.allは失敗を1つでも受けると拒否されるため、全件成功が必要か、失敗を個別に記録するかを先に決めます。
開始ボタンの無効化だけでなく、メイン側にも実行中のガードを置きます。キャンセルはフラグを受けて、次に処理が制御を返した位置で停止する仕組みです。進捗を表示しただけで重い処理が速くなるわけではありません。
具体例は分割してCSVを書き出す実装とプログレスバーを参照してください。
ビルド・エラー・終了を区別する
TypeScriptのソースではなく、生成したJavaScriptをmanifestのmainに指定します。mainやuiの相対パス、生成ファイルの有無を確認すると、ENOENTなどのファイル参照エラーを切り分けられます。JSONには末尾のカンマを残しません。
optional chainingやnullish coalescingを一律に未対応とは断定せず、対象環境とビルド結果を確認します。nullish coalescingを真偽値の判定へ置き換えると、0・false・空文字まで既定値になるため、意味を保つ必要があります。
処理と保存操作が終わったら、figma.closePlugin()でUIとタイマーを終了します。
保存用のUIを先に閉じるとダウンロード操作ができなくなるため、保存と終了を分けます。
closePlugin()を呼んでも、その後に続くJavaScriptの行は実行されます。
関数内で終了を判断した場合は、直後にreturnを置き、その関数の残りを実行しないようにします。
終了後にFigma APIへアクセスすると例外になるため、呼び出し元でも後続のAPI操作へ進まない構成にします。
出典:closePluginとshowUI、closePluginの終了後の挙動(2026年10月28日確認)。
検証範囲と関連ガイド
今回の整理は公式資料と本サイトの開発例に基づいています。各APIのFigmaデスクトップアプリ上での再現をすべて確認したものではありません。
開発環境と登録手順はFigmaプラグイン開発入門、公開はCommunityへの申請を参照してください。
よくある質問:Figmaプラグイン開発の注意点で迷ったときのチェックリスト
プラグインのメインコードとUIは、何が違いますか?
メインコードでは、figma APIでノード・スタイルの取得や変更をします。HTMLの入力欄、Blob、ダウンロードはUIのiframeで扱います。ブラウザー用のコードをそのままメイン側へ貼ると、DOM操作や保存処理などが動かないことがあります。
ノードのオブジェクトを、UIにそのまま渡してよいですか?
渡さないでください。ID・名前など、必要な値に変換します。UI側のmessageはparentからのものか確認し、メイン側でもtypeと値を確認します。表示する名前は、任意のレイヤー名をHTMLとして挿入しないよう注意します。
dynamic-pageでは、どのAPIを使いますか?
新しいmanifestのdocumentAccessは、dynamic-pageを前提にします。getNodeByIdAsyncなどの非同期APIをawaitし、nullや拒否を処理します。同期版の名前を非同期版へ変えるだけでなく、呼び出す関数とその利用側もasync/awaitにします。
テキストを変える前に、何が必要ですか?
文字や文字サイズなど表示に関わる変更では、loadFontAsyncが必要です。混在フォントを1つのfontNameとして渡すのではなく、変更範囲のフォントを調べます。
大量のノードを処理するときの注意点は?
大量のノードへ無制限にPromiseを作ると負荷が増えます。件数を区切り、適切な間隔で進行状況をUIへ送ります。進捗を表示しただけで、重い処理が速くなるわけではありません。
manifestのmainには、何を指定しますか?
TypeScriptのソースではなく、生成したJavaScriptを指定します。mainやuiの相対パス、生成ファイルの有無を確認すると、ENOENTなどのファイル参照エラーを切り分けられます。
