javascriptnode.jsvscode-extensions

When using @tomjs/vite-plugin-vscode, blank page is shown, but only in dev mode


I'm using @tomjs/vite-plugin-vscode to build a VS Code extension with Vue. I started from a WebView Provider, partially following its minimal example.

vite.config.mts:

import pluginVscode from '@tomjs/vite-plugin-vscode';
import pluginVue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    pluginVscode({
      recommended: true,
    }),
    pluginVue({
      template: {
        compilerOptions: {
          isCustomElement: tag => tag.startsWith('vscode-'),
        },
      },
    }),
  ],
});

The below is my extension code.

index.ts:

import * as vscode from 'vscode';
import { createWebviewProvider } from './webview';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    createWebviewProvider(context),
  );
  const disposable = vscode.commands.registerCommand('oi-runner-2.focus', () => {
    vscode.window.showInformationMessage('Focus!');
  });

  context.subscriptions.push(disposable);
}

webview.ts:

import process from 'node:process';
import * as vscode from 'vscode';

/**
 * @see https://github.com/tomjs/vite-plugin-vscode/blob/v3.0.0/examples/vue/extension/views/helper.ts#L4-L8
 */
function getHtml(webview: vscode.Webview, context: vscode.ExtensionContext) {
  return process.env.VITE_DEV_SERVER_URL
    ? __getWebviewHtml__(process.env.VITE_DEV_SERVER_URL)
    : __getWebviewHtml__(webview, context);
}

class PanelProvider implements vscode.WebviewViewProvider {
  static readonly VIEW_TYPE = 'oi-runner-2.panel';

  constructor(private _context: vscode.ExtensionContext) {}

  resolveWebviewView(webviewView: vscode.WebviewView) {
    webviewView.webview.options = {
      enableScripts: true,
      localResourceRoots: [
        vscode.Uri.joinPath(this._context.extensionUri, 'dist'),
      ],
    };
    webviewView.webview.html = getHtml(webviewView.webview, this._context);
  }
}

export function createWebviewProvider(context: vscode.ExtensionContext) {
  return vscode.window.registerWebviewViewProvider(
    PanelProvider.VIEW_TYPE,
    new PanelProvider(context),
    {
      webviewOptions: {
        retainContextWhenHidden: true,
      },
    },
  );
}

The webview code follows the example.

I expect WebView Provider appears after toggling the command. What is strange, it works fine in production mode, but in dev mode it shows nothing.

Environment:


Solution

  • Look at this line:

    import process from 'node:process';
    

    It overrides Node.js global variable process, though they are exactly the same object.

    @tomjs/vite-plugin-vscode internally use tsup to build extension code, which internally use rollup. The plugin passed env option to rollup in order to replace process.env.VITE_DEV_SERVER_URL.

    However, rollup recognised import process, then treat process as imported symbol, but not Node.js global variable. So process.env.VITE_DEV_SERVER_URL won't be replaced - evaluate as undefined at runtime, leading to a blank page.

    To solve this, just remove the import.


    I posted this on GitHub last week, and now I am posting it here to prevent more people from falling into the trap in the future.

    Also added the tip to tsup docs.