With Webview, you can build a complex UI for users of your extension. And its development is not a hard work:
- Design html page
- Create a WebviewPanel
- Handle messaging between html and WebviewPanel
In Webview API Document, you can find all you want to kick off this job.
However, as doing that 3-step development cycle again and again, you may find there are some repetive tasks:
- local resource root setting
- Need to transform relative paths to "vscode-resource" scheme.
- createOrShow logic
- retainContextWhenHidden setting
- the boilerplate code for messaging handling
- In html page, adding an event listener to change partial content in the same page based on response from WebviewPanel.
- In WebviewPanel, creating a message processor for all messages from html page.
Based on DRY, if we could abstract away all these tasks, we could spend more time writing business logic. That's why vscode-page comes.
What is vscode-page
vscode-page is a light-weight page micro framework for vscode webview, it could accelerate Vs Code Extension Webview development.
Its features:
- abstract away communication between html page and WebviewPanel.
- built-in template engine, with handlebars.js.
- message mapping, a simple way to organize message handler and view.
- baseUrl support, relative paths can be used in html page.
And here is its archtecture:
Now, it is time to see how to use it to simplify our vscode Webview development.
How to use vscode-page
Let's create a "hello world" extension project to show its usage: this extension will load a html page by a command, at the same time a "hello world" will be passed from WebviewPannel to that html page which will show it.
First, create an extension project and install its dependencies:
yo code hello-page
...
cd hello-page
npm install --save vscode-page
npm install --save handlebars.js
Then, replace all lines in extension.ts with the followings:
import * as vscode from "vscode";
import { createOrShowPage } from "vscode-page";
export function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "hello-page" is now active!');
let disposable = vscode.commands.registerCommand(
"extension.helloWorld",
() => {
createOrShowPage(
"name", // name
"ext.home", // viewType
"Hello Page", // title
"pages", // localResourceRoot
"hello.html", // html
context, // vscode.ExtensionContext
[
// Message Mappings
{
command: "ready", // command from js function in html
// message handler
handler: async () => {
return {
body: "hello world"
};
},
// views changed by handler returning
// [{element-id, handlebars-template}]
templates: [{ id: "content", content: "{{body}}" }]
}
]
);
}
);
context.subscriptions.push(disposable);
}
export function deactivate() {}
Finally, create hello.html in pages directory which is at the same level as src directory. And its content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- MUST be added -->
<base href="{{base}}" />
<!-- MUST be added -->
<script type="text/javascript">"{{init}}"</script>
<title>Hello Page</title>
</head>
<body>
<h1>vsode-page Hello World</h1>
<!-- element id must be the same template id in MessageMapping -->
<div id="content"></div>
<script type="text/javascript">
initEventListener(); // initialize
const vscode = acquireVsCodeApi();
vscode.postMessage({
command: "ready" // command sent to MessageMappings
});
</script>
</body>
</html>
That's it! Now, you can build and start this extension to check result.
Conclusion
With vscode-page, you don't bother repeating yourself, only focus on core business logics:
- Message format between html page and WebviewPanel
- Fine-graded handlers for each message
- HTML page layout, js function and view templates
Although is a toy project shown in this post, you can find a more complex example in its repository. Also, you can find more details in README.
Top comments (0)