これは、農工大2025アドベントカレンダーの記事です。
はじめに
VS Code 拡張機能開発において、標準の UI だけでは実現できないリッチな表現が必要な場合に Webview API を使用した事例を紹介します。
Webview とは
VS Code 内に完全にカスタマイズ可能なビューを作成できる API です。 HTML、CSS、JavaScript を使用して、Web ブラウザのようなインターフェースをエディタ内に構築できます。
背景・動機
拡張機能を作っていると、「グラフを表示したい」「複雑なフォームを作りたい」「動画を埋め込みたい」といった、エディタ標準の TreeView や InputBox では対応しきれない要件が出てきます。 そんな時、自由度の高い Webview が唯一の解決策となることが多いです。
Webview 開発の「つらさ」
Webview は強力ですが、開発には独特の「つらさ」があります。
1. リソース読み込みの制限 (CSP & URI Scheme)
普段の Web 開発のように <script src="script.js"></script> と書いても動きません。
VS Code のセキュリティポリシー (Content Security Policy) に準拠する必要があり、かつローカルファイルへのパスは vscode-resource:/ のような特殊なスキーマに変換しなければなりません。
2. メッセージパッシングの複雑さ
Webview (HTML側) と Extension (Node.js側) は隔離された環境で動作するため、変数の直接共有ができません。
postMessage を介した非同期なメッセージのやり取りが必要となり、コードが複雑になりがちです。
実装のポイント
今回は、これらの課題を乗り越えてシンプルな Webview 拡張機能を作成する手順を解説します。
1. コマンド登録とパネルの作成
まずは Webview を表示するための「枠(パネル)」を作ります。
createWebviewPanel を使用しますが、ここで enableScripts: true を忘れると JS が動かないので注意です。
// extension.ts
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand('vscodewebview.start', () => {
// パネルの作成
const panel = vscode.window.createWebviewPanel(
'webviewDemo', // 内部的な識別子
'Webview Demo', // タイトル
vscode.ViewColumn.One,
{
enableScripts: true, // JSを有効化 (必須!)
retainContextWhenHidden: true // 裏に回っても状態を維持
}
);
// HTMLコンテンツを設定
panel.webview.html = getWebviewContent();
// ...後述のメッセージ処理
});
context.subscriptions.push(disposable);
}
2. HTML/CSS/JS の分離と読み込み
HTML を文字列でベタ書きするのは辛いので、外部ファイル化するのが定石です。
リソースパスの変換には asWebviewUri を使用します。これにより、Webview 内からローカルファイルへ安全にアクセスできるようになります。
import * as path from 'path';
// ディスク上のパスを取得
const scriptPathOnDisk = vscode.Uri.file(
path.join(context.extensionPath, 'media', 'script.js')
);
// Webview用のURIに変換 (例: https://file+.vscode-resource.vscode-cdn.net/...)
const scriptUri = panel.webview.asWebviewUri(scriptPathOnDisk);
// HTML内で使用
// return `... <script src="${scriptUri}"></script> ...`;
3. 双方向通信 (Messaging)
Webview から Extension へ通知を送る実装です。 例えば、「ボタンが押されたら VS Code の通知を出す」といった連携が可能になります。
Webview 側 (送信):
acquireVsCodeApi() は一度しか呼べないため、定数に保持して使います。
<script>
const vscode = acquireVsCodeApi();
function sendMessage() {
vscode.postMessage({
command: 'alert',
text: 'Hello from Webview!'
});
}
</script>
Extension 側 (受信):
onDidReceiveMessage でメッセージを待ち受けます。
panel.webview.onDidReceiveMessage(
message => {
switch (message.command) {
case 'alert':
vscode.window.showInformationMessage(message.text);
return;
}
},
undefined,
context.subscriptions
);
まとめ
Webview を使うと、VS Code の拡張機能開発の幅が一気に広がります。 リソース管理やメッセージングの仕組みさえ理解してしまえば、あとは通常の Web フロントエンド開発の知識がそのまま活かせます。
ぜひ、オリジナルのリッチな UI を持った拡張機能を作ってみてください!