Loading node_modules Resources in VSC WebView

Recently, while developing the gitlink plugin, I encountered an issue loading node_modules resources in WebView. Although CDN resources could be used directly, loading local resources is faster. Here’s how to solve the loading of node_modules resources.

Configuration

  1. Install npm dependency
1
npm install @highlightjs

Note that this should be a dependency, not a dev dependency.

  1. Configure localResourceRoots in webview
1
2
3
4
5
6
7
8
9
10
11
12
const panel = vscode.window.createWebviewPanel(
'codeImage',
'Code Snippet Image',
vscode.ViewColumn.Beside,
{
enableScripts: true,
retainContextWhenHidden: true,
localResourceRoots: [
vscode.Uri.joinPath(extensionContext.extensionUri),
]
}
);

Here, we use extensionContext.extensionUri as localResourceRoots, allowing us to access node_modules resources within the extension.

  1. Load resources in webview
1
<link rel="stylesheet" href="node_modules/@highlightjs/cdn-assets/styles/github-dark.min.css">

Please note that relative path syntax is preferred over absolute path syntax. Absolute paths are not supported, but web addresses are.

  1. Handle HTML href paths
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const readHtml = async (htmlPath: string, panel: vscode.WebviewPanel) =>
(fs.readFileSync(htmlPath, {
encoding: 'utf8'
}))
.replace(/%CSP_SOURCE%/gu, panel.webview.cspSource)
.replace(
/(src|href)="([^"]*)"/gu,
(_, type, src) =>
`${type}="${panel.webview.asWebviewUri(
vscode.Uri.file(path.resolve(htmlPath, '../../../', src))
)}"`
);


this._panel.webview.html = await this._getHtmlContent(code, language, options);

let htmlTemplate = await readHtml(
path.resolve(this._extensionContext.extensionPath, 'resources/webview/index.html'),
this._panel
);

This is how I handle it - processing all resources in the HTML based on the HTML’s location to obtain the path relative to the extension for node_modules resources.

Note

  • Don’t add the node_modules folder in the .vscodeignore file. Otherwise, the package won’t include node_modules.

At the end

Following these steps solves the issue of loading node_modules resources in WebView. When updates are needed in the future, run the npm update and repackage the extension.