VSCode: Escaping WebView iframe
Tags: vscode, webvie, iframe, extensions
Published: 2023-09-17 12:46:21

When developing extensions for VSCode using a favored frontend framework like React, Svelte, or Vue.js, a common hurdle encountered is the communication between the VSCode environment and the WebView where your app is rendered. Traditionally, acquireVsCodeApi() is employed to facilitate this, but it becomes undefined once you start using iframe with URL as src, bringing the postMessage API out of reach and crippling the interaction.

In light of this, you could use a strategy that turns extension.ts into a Socket.io server while WebView leverages a locally running React app with a Socket.io client, fostering real-time bi-directional event-based communication.

## Setting the Stage
Your extension.ts would take on the role of a Socket.io server, initiating a pathway for continuous communication. Parallelly, the WebView would harbor a React application tuned to be a client for the Socket.io server.

## Establishing the Connection
**VSCode Extension Side**

First, install the necessary socket.io package in your extension project:

```sh
$ npm install socket.io
```

Next, in your extension.ts file, initialize the socket.io server:

```ts
import { createServer } from "http";
import { Server } from "socket.io";

const httpServer = createServer();
const io = new Server(httpServer);
io.on("connection", (socket) => {
  console.log("New client connected");
  
  // Listen for messages from the client
  socket.on("messageFromClient", (msg) => {
    console.log("Received message from client:", msg);
  });

  // Sending a welcome message to the client
  socket.emit("messageFromServer", { data: "Hello, client!" });
});
```

## React App Side

Install socket.io-client in your React project:

```sh
$ npm install socket.io-client
```

In your main React component, initialize the socket.io client and set up event listeners to communicate with the server:

```tsx
import { useEffect } from "react";
import { io } from "socket.io-client";

// port can be passed as a query parameter
const port = new URLSearchParams(window.location.search).get('port')
const socket =  io(`http://localhost:${port}`);

function App() {
  useEffect(() => {
    // Listen for messages from the server
    socket.on("messageFromServer", (msg) => {
      console.log("Received message from server:", msg);
    });
    
    // Sending a message to the server
    socket.emit("messageFromClient", { data: "Hello, server!" });
  }, []);
  
  return <div className="App">Socket.io with VSCode</div>;
}

export default App;
```

## Securing the Communication

Leveraging socket.io for real-time communication opens up a new dimension of interaction between VSCode and WebView, but it comes with its share of security concerns. Securing the data transmitted over the socket is crucial to safeguard sensitive information and maintain user trust.

## Conclusion
This communication pathway between extension.ts and a frontend app within WebView, championed by socket.io, promises a rich, real-time bi-directional communication unhindered by the traditional restrictions of VSCode's WebView iframe.

Please share your perspectives and join in refining this architectural blueprint.