This repo contains the boilerplate needed to quickly get your own VS Code Extension up and running using React Webviews.
- Easy to add new custom React-based Webviews
- Fast Refresh during local development
- Type-safe API for bidirectional postMessage communication
First make sure you have git, Node v18 and VS Code installed, then run:
$ git clone [email protected]:sfc-gh-tkojima/vscode-react-webviews.git
$ cd vscode-react-webviews
$ npm install
$ code .
- Run and Debug (
F5
)
Once launched you will see a new T-shirt icon in the left side bar. Click on it to activate the extension. The extension includes two sample Webviews to showcase the provided functionality:
- ExampleViewA
- Provides a button to open the ExampleViewB window
- Allows users to send messages from ExampleViewA to ExampleViewB
- ExampleViewB
- Provides a Load File button that will call into the host process to read a file and render its text contents in the Webview
- Listens for and displays messages sent from ExampleViewA
- If the VS Code host window opens and then closes immediately or fails to open, view the output for why it failed.
- In one case, not having all the recommended extensions (namely, the Typescript + Webpack Problem Matchers one) installed can cause the host window not to start up at all. See .vscode/extensions.json for the list of recommended extensions.
Adding a new view requires you to update 3 files:
-
package.json
Add your view to the
contributes.views
section -
src/views/index.tsx
Add your view to the Views const. They key should match the id you specified in
package.json
export const Views = { exampleViewA: ExampleViewA, exampleViewB: ExampleViewB, } as const;
-
src/extension.ts
Call
registerAndConnectView("newViewId");
inside the activate function.
To add a new postMessage API, update the ViewApi
type in src/viewApi.ts
. Then update the api
object insrc/extension.ts
with a matching implementation.
To call the API from a Webview use the callApi
function available on WebviewContext
:
import { useContext, useState } from "react";
import { WebviewContext } from "./WebviewContext";
...
export const ExampleViewA = () => {
const {callApi} = useContext(WebviewContext);
callApi("showInformationMessage", 'Hello there!');
};
Events are even easier to add than APIs. Update the ViewEvents
type in src/viewApi.ts
. You can then call triggerEvent()
with your new event inside extension.ts
.
To listen to thew new event from inside a Webview, use the addListener
and removeListener
functions on WebviewContext
:
import { useContext, useEffect, useState } from "react";
import { WebviewContext } from "./WebviewContext";
export const ExampleViewB = () => {
const { callApi, addListener, removeListener } = useContext(WebviewContext);
const [messages, setMessages] = useState<string[]>([]);
useEffect(() => {
const cb = (msg: string) => {
setMessages([...messages, msg]);
};
addListener("exampleBMessage", cb);
return () => {
removeListener("exampleBMessage", cb);
};
}, [messages]);
};
You must use useEffect
with addListener
so that you can call removeListener
whenever the component unmounts.
Sourcemaps are configured for both the extension host and view bundles. Setting breakpoints in VS Code editor windows will work out-of-the box!
To build your extension so you can distribute or publish it, run npm run build
. This will output a vsix
file into the build
directory. You can then publish this to the VS Code Marketplace or install it manually.
For more info, consult the VS Code docs.