当连接到远程工作区时,为什么 localhost 在我的 VS Code 的 Web 视图中不起作用?

Why does localhost not work inside my VS Code's webviews when connected to remote workspaces?

我有一个简单的扩展程序,它使用 VS Code's webview api 从我的扩展程序生成的服务器加载内容。它使用指向 localhost:

的 iframe 执行此操作
import * as vscode from 'vscode';
import * as express from 'express';

const PORT = 3000;

export function activate(context: vscode.ExtensionContext) {

    // Spawn simple server
    const app = express();
    app.get('/', (_req, res) => res.send('Hello VS Code!'));
    app.listen(PORT)

    context.subscriptions.push(
        vscode.commands.registerCommand('myExtension.startPreview', () => {
            const panel = vscode.window.createWebviewPanel('myExtension.preview', 'Preview', vscode.ViewColumn.One,
                {
                    enableScripts: true
                });

            panel.webview.html = `<!DOCTYPE html>
            <html lang="en"">
            <head>
                <meta charset="UTF-8">
                <title>Preview</title>
                <style>
                    html { width: 100%; height: 100%; min-height: 100%; display: flex; }
                    body { flex: 1; display: flex; }
                    iframe { flex: 1; border: none; background: white; }
                </style>
            </head>
            <body>
                <iframe src="http://localhost:${PORT}"></iframe>
            </body>
            </html>`
        }));
}

当扩展在本地运行时这很好用,但是当我尝试 运行 我在 remote workspace 中的扩展时,iframe 是空的:

为什么会发生这种情况,我该如何解决?

在远程工作区的 web 视图中使用 localhost 时,这是预期的。根本原因是 webviews 加载在用户的本地机器上,而您的扩展在远程机器上 运行ning:

对此有两种可能的修复方法:

将您的扩展标记为 UI Extension,这样它在本地机器上总是 运行。

如果扩展不需要从工作区读取文件或使用只能随工作区一起安装的 scripts/tools,则可以将扩展设置为 UI 扩展。 UI 扩展在用户的本地机器上 运行,所以它生成的服务器可以使用 localhost

访问

只需将 "extensionKind": "ui" 添加到您的分机的 package.json 即可。

为您的 webview 配置端口映射

VS Code 端口映射 API 允许您将 webview 中使用的本地主机端口映射到扩展名为 运行ning 的机器上的任意端口。如果您的分机是 运行ning 远程,这甚至可以工作。

VS Code 1.34 中添加了端口映射 API。要使用它,请在创建 webview 面板时传入一个 portMapping 对象:

const panel = vscode.window.createWebviewPanel('myExtension.preview', 'Preview', vscode.ViewColumn.One,
    {
        enableScripts: true,
        // This maps localhost:3000 in the webview to the express server port on the remote host.
        portMapping: [
            { webviewPort: PORT, extensionHostPort: PORT}
        ]
    });

如果您的 webview 出于任何原因使用本地主机,最好设置 portMapping 以便它可以在任何地方正确地 运行。实际上,您还应该考虑随机选择服务器 运行 所在的端口。使用端口映射,您无需为此更改 webview 的 html:

{ webviewPort: 3000, extensionHostPort: RANDOM_PORT_SERVER_WAS_STARTED_ON }

See the VS Code docs for more details