You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在VSCode扩展中使用Vite(react-ts)生成WebView脚本?

用Vite + React-TS构建VSCode扩展WebView的可行性与配置方案

完全可行,Vite的快速构建能力搭配React-TS的类型安全特性,非常适合开发VSCode WebView,既能提升开发效率,也能保证代码的可维护性。下面是具体的配置步骤:

一、初始化项目结构

  • 先通过官方脚手架初始化TypeScript版VSCode扩展项目:
    yo code # 选择TypeScript模板生成基础结构
    
  • 进入扩展项目根目录,用Vite创建React-TS子项目:
    npm create vite@latest webview-ui -- --template react-ts
    

二、配置Vite打包输出路径

修改webview-ui/vite.config.ts,把打包产物输出到扩展能直接访问的目录(比如根目录下的media文件夹),同时配置相对路径适配WebView的资源加载:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  build: {
    outDir: '../media', // 输出到扩展根目录的media文件夹
    emptyOutDir: true,
  },
  base: './', // 相对路径避免WebView资源加载失败
})

三、扩展端配置WebView加载逻辑

在扩展主文件src/extension.ts中,修改WebView创建逻辑,加载Vite打包后的HTML文件:

import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';

export function activate(context: vscode.ExtensionContext) {
  const showWebview = vscode.commands.registerCommand('your-extension.openWebview', () => {
    const panel = vscode.window.createWebviewPanel(
      'customWebview',
      '我的WebView',
      vscode.ViewColumn.One,
      {
        enableScripts: true,
        // 允许WebView访问media目录下的资源
        localResourceRoots: [vscode.Uri.file(path.join(context.extensionPath, 'media'))]
      }
    );

    // 读取打包后的HTML文件
    const htmlPath = path.join(context.extensionPath, 'media', 'index.html');
    const htmlContent = fs.readFileSync(htmlPath, 'utf8');
    panel.webview.html = htmlContent;
  });

  context.subscriptions.push(showWebview);
}

注意:确保tsconfig.json中配置了"moduleResolution": "node",这样才能正常导入fs和path模块。

四、开发阶段热重载配置

开发时不想每次打包?可以配置Vite开发服务器,让WebView直接访问实时更新的页面:

  1. 修改webview-ui/vite.config.ts添加服务器配置:
server: {
  port: 5173,
  strictPort: true, // 固定端口避免冲突
}
  1. 在src/extension.ts中添加开发环境判断,切换加载逻辑:
// 创建WebViewPanel后添加以下逻辑
const isDev = process.env.NODE_ENV === 'development';

if (isDev) {
  // 开发环境嵌入Vite dev server的页面
  panel.webview.html = `
    <!DOCTYPE html>
    <html>
      <body style="margin:0;padding:0;">
        <iframe src="http://localhost:5173" frameborder="0" style="width:100%;height:100vh;"></iframe>
      </body>
    </html>
  `;
} else {
  // 生产环境加载打包后的HTML
  const htmlPath = path.join(context.extensionPath, 'media', 'index.html');
  const htmlContent = fs.readFileSync(htmlPath, 'utf8');
  panel.webview.html = htmlContent;
}
  1. 在扩展根目录的package.json中添加快捷脚本,同时启动扩展和Vite开发服务器:
"scripts": {
  "vite:dev": "cd webview-ui && npm run dev",
  "extension:dev": "code . --extensionDevelopmentPath=. && npm run watch",
  "dev": "concurrently \"npm run vite:dev\" \"npm run extension:dev\""
}

执行npm install concurrently --save-dev安装依赖包,之后直接跑npm run dev就能同时启动两个服务。

五、类型安全的WebView通信

既然扩展和WebView都是TS开发,能轻松实现类型安全的消息通信:

  1. 在扩展根目录创建共享类型文件src/types/webview.ts:
export type MessageType = 'fetchData' | 'returnData';

export interface WebViewMessage {
  type: MessageType;
  payload?: {
    data?: string;
    error?: string;
  };
}
  1. 在WebView项目中导入该类型(通过相对路径),实现消息收发:
import type { WebViewMessage } from '../../src/types/webview';

// 发送消息到扩展
const sendMessageToExtension = (message: WebViewMessage) => {
  window.postMessage(message, '*');
};

// 监听扩展发来的消息
window.addEventListener('message', (event) => {
  const msg: WebViewMessage = event.data;
  if (msg.type === 'returnData') {
    console.log('收到扩展返回的数据:', msg.payload?.data);
  }
});
  1. 在扩展的extension.ts中监听并响应WebView消息:
panel.webview.onDidReceiveMessage(
  (msg: WebViewMessage) => {
    switch (msg.type) {
      case 'fetchData':
        // 模拟获取数据
        panel.webview.postMessage({
          type: 'returnData',
          payload: { data: '这是扩展返回的数据' }
        });
        break;
    }
  },
  undefined,
  context.subscriptions
);

内容的提问来源于stack exchange,提问作者zarigani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 07:07:06