VSCode Webview 插件开发的模板的踩坑记录

前言

上周写了个 vscode 的小插件后,突然想整个 webview 的插件。

于是乎开始搜罗相关的资料,开搞!这里记录下几个踩过的坑。

问题

CSP: refused xxxxxx

常见的几类报错(打开开发者工具,在控制台就会自动输出)

  • refused to apply inline style because it violates the following Content Security Policy directive xxxxxx
  • refused to load the script '' because it violates the following Content Security Policy directiv

VSCode webview 对于资源的注入很严格!!

目前的策略是把 web 站点打包成一个index.js和 index.css去注入!

资源链接必须转换成 vscode 允许的资源格式!!!

typescript 复制代码
//path: src/panels/VueBoilerplatePanel.ts
private _getWebviewContent(webview: Webview, extensionUri: Uri) {
// The CSS file from the Vue build output
const stylesUri = getUri(webview, extensionUri, ["webview-ui", "build", "assets", "index.css"]);
// The JS file from the Vue build output
const scriptUri = getUri(webview, extensionUri, ["webview-ui", "build", "assets", "index.js"]);
const nonce = getNonce();

// Tip: Install the es6-string-html VS Code extension to enable code highlighting below
return /*html*/ `
  <!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <meta http-equiv="Content-Security-Policy" content="default-src 'none';connect-src https:; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} https: data:; script-src 'nonce-${nonce}';">
      <link rel="stylesheet" crossorigin nonce="${nonce}" type="text/css" href="${stylesUri}">
      <script type="module" nonce="${nonce}" src="${scriptUri}"></script>
      <title>Hello World</title>
    </head>
    <body>
      <div id="app"></div>
    </body>
  </html>
`;
}
  1. meta的 csp 策略进行了修改,允许加载部分资源,而不是默认各种卡死,对 web 开发友好
  2. index.htmlscriptlink 标签的 srchref 都进行了转换,还有 hash 防缓存

上面的 csp 设置值的简单介绍

施加策略的目录 允许潜在的源列表 描述
default-src 'none' 默认情况下,禁止所有资源类型的加载。
connect-src https: 仅允许通过 https 协议进行 XMLHttpRequest,Fetch 加载资源等操作。
style-src ${webview.cspSource} 'unsafe-inline' 允许从 webview.cspSource 和内联样式加载样式。
img-src ${webview.cspSource} https: data: 允许从 webview.cspSource、https 协议和 data 协议(即base64 编码的图片)加载图片。
script-src 'nonce-${nonce}' 仅允许加载具有特定 nonce 值的脚本。

如何打包所有文件到一个index.js 和 index.css

  • css和js需要打包成单独文件
typescript 复制代码
// path: webview-ui/vite.config.ts

build: {
modulePreload: false, // 关闭预加载
outDir: "build", // 打包输出目录
emptyOutDir: true, // 打包之前清空build 文件夹
assetsInlineLimit: 99999999999, // 默认是4096
rollupOptions: {
  output: {
    entryFileNames: `assets/[name].js`, // 打包后的入口文件
    chunkFileNames: `assets/[name].js`,
    assetFileNames: `assets/[name].[ext]`,
    manualChunks: (id: string) => { // 打包后的静态资源,自定义策略,全部合并到 index
      return 'index'
    }
  },
},
},
  • png这类静态图片直接打包成base64(参考上面的 assetsInlineLimit)

  • svg 用 vite-svg-loader, 默认转换为 Component

typescript 复制代码
// path: webview-ui/vite.config.ts
svgLoader({ defaultImport: 'component' }),

// 在使用层面可以通过 query(?) 来转换 svg 为内联或者其他
// 具体可以去看这个插件的介绍,挺强大的

开发模式 dev

从项目结构上来看,里面就是两个工程,所以要运行两条命令;

  • 一条是打包 webview 网站输出静态资源
  • 一条是编译插件源码输出插件入口文件

那有什么可以同时运行并输出信息的呢? 我用concurrently来解决了我的这个困扰。

仓库

开源项目名称 vscode-webview-vite-vue-boilerplate
开源项目地址 github.com/crper/vscod...

tips: webview-ui(仓库内)

这是一个基于Vite 5 + Vue3 + TypeScript + UnoCSS + Vue Router + Pinia + Naive UI的项目模板,相关的初始化和配置都有,"五脏俱全",算是一个 mvp demo 项目,有兴趣的可以看看瞅瞅。

webview的 debug

基本绝大多数异常都是在开发者工具里面的控制台看,vscode 本身就是基于 electron 搞的,内核 chromium。 做了一些系统交互接口和更加严格的资源策略模式,类似各种沙盒机制!!但本质上还是"浏览器"!!

结语

有不对之处请留言,谢谢阅读

相关推荐
曼陀罗5 小时前
【pnpm、npm】各种命令详解
npm·node.js·前端工程化
全宝17 小时前
🧑‍💻[2025最新]用oh-my-posh打造个性化终端
程序员·操作系统·visual studio code
阿里云云原生1 天前
Python3 AI 通义灵码 VSCode插件安装与功能详解
后端·python·visual studio code
Selicens1 天前
VSCode Snippets 魔改专属的 vue 代码片段
vue.js·visual studio code
阿里云云原生1 天前
Python2 AI 通义灵码 VSCode插件安装与功能详解
python·visual studio code
lilye661 天前
程序化广告行业(71/89):ABTester与Tag Manager系统深度解析
visual studio code·odps
东望2 天前
写代码不规范,同事两行泪 😭(工程化如何让团队协作更高效)
javascript·前端工程化
爱抽烟的大liu2 天前
原生开发与H5开发:探索两者的优势及应用场景
前端工程化
莫循瑾木2 天前
如何在大型项目中有效使用TypeScript进行类型定义?
前端·typescript·前端工程化
阿虎儿2 天前
VS Code 的 launch.json 进行高效代码调试:配置和原理解析
前端·visual studio code