A VSCode Sidebar Webview Extension With React
vscode-webview-extension-with-react README
vscode-webview-extension-with-react is a repo to illustrate how to register a webview using react to side bar of vscode when developing vscode extension
1. Create a webview to VScode extension side panel
-
In
package.jsonwe need to register a view container to have a icon in side bar``` "viewsContainers": { "activitybar": [ { "id": "webview", "title": "Example for webview", "icon": "./assets/extension-icon.png" } ] }, "views": { "webview": [ { "type": "webview", "id": "left-panel-webview", "name": "Webview", "icon": "src/assets/extension-icon.png" } ] } ``` -
Create a webview provider
LeftPanelWebviewwhich is implemented fromWebviewViewProvider- Note that:
-
We can assign data from extension to this webview such as
extensionPathwhen createLeftPanelWebviewclass -
resolveWebviewViewwill be the function calling first we open the webview -
_getHtmlForWebviewwill be the function to render the webview from react -
The script for the webview can be register in the
bodyof webview<script nonce="${nonce}" type="text/javascript" src="${constantUri}"></script> <script nonce="${nonce}" src="${scriptUri}"></script> -
For styling, let add CSS file to
linktag<link href="${styleUri}" rel="stylesheet">
-
- Note that:
-
Declare
LeftPanelWebviewclass and register Webview inextension.tsconst leftPanelWebViewProvider = new LeftPanelWebview(context?.extensionUri, {}); let view = vscode.window.registerWebviewViewProvider( EXTENSION_CONSTANT.LEFT_PANEL_WEBVIEW_ID, leftPanelWebViewProvider, ); context.subscriptions.push(view);
-
Then you will have a webview in side panel !!
2. How to render react component in vscode and handle user action
- When calling Webview for the first time,
_getHtmlForWebviewwill be called and expect to return the html file of the webview. We will useReactDOM.renderToStringto concat the react component intobodytag of the html file. In that case, react component will be rendered.
<body>
${
ReactDOMServer.renderToString((
<LeftPanel message={"Tutorial for Left Panel Webview in VSCode extension"}></LeftPanel>
))
}
<script nonce="${nonce}" type="text/javascript" src="${constantUri}"></script>
<script nonce="${nonce}" src="${scriptUri}"></script>
</body>
-
The weakness of this approach is the webview will only be a static html view. Because of this problem, we will need to embedded the script into html so that we can handle user action base on eventListener from DOM
-
We can also handle user action in script and callback to our extension by using
vscode.postMessagein script file and use_view.webview.onDidReceiveMessageto receive the message in webview components// Script file: Emit message vscode.postMessage({ action: POST_MESSAGE_ACTION.SHOW_WARNING_LOG, data: { message: "You just clicked on the left panel webview button" }});this._view.webview.onDidReceiveMessage((message) => { switch (message.action){ case 'SHOW_WARNING_LOG': window.showWarningMessage(message.data.message); break; default: break; } }); -
Using this way of communication between webview and extension, we also can create a message chanel between 2 separated webview in some complicated vscode extension
If you have any further question, feel free to contact luongquochuy1995@gmail.com