问题
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> `; }
meta
的 csp 策略进行了修改,允许加载部分资源,而不是默认各种卡死,对 web 开发友好index.html
的script
和link
标签的src
和href
都进行了转换,还有 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 为内联或者其他 // 具体可以去看这个插件的介绍,挺强大的
路由模式
因为内嵌 webview 不像浏览器有路由导航栏这些,一般 webview 没有前进后退的概念,这种我们的路由跳转优先采用内存路由(memory router), 它非常适合需要完全控制历史堆栈的场景, 类似 Vue 或者 React 都有提供!!
开发模式 dev
从项目结构上来看,里面就是两个工程,所以要运行两条命令;
- 一条是打包 webview 网站输出静态资源
- 一条是编译插件源码输出插件入口文件
那有什么可以同时运行并输出信息的呢? 我用concurrently来解决了我的这个困扰。
webview的 debug
基本绝大多数异常都是在开发者工具里面的控制台看,vscode 本身就是基于 electron 搞的,内核 chromium。 做了一些系统交互接口和更加严格的资源策略模式,类似各种沙盒机制!!但本质上还是“浏览器”!!
仓库
开源项目名称 | vscode-webview-vite-vue-boilerplate |
---|---|
开源项目地址 | github.com/crper/vscod… |
Demo视频 | www.yuque.com/crper/blog/… |
tips: webview-ui(仓库内)
这是一个基于Vite 5 + Vue3 + TypeScript + UnoCSS + Vue Router + Pinia + Naive UI的项目模板,相关的初始化和配置都有,“五脏俱全”,算是一个 mvp demo 项目,有兴趣的可以看看瞅瞅。
标签:index,插件,src,VSCode,js,build,webview,Webview,打包 From: https://blog.csdn.net/weixin_47588164/article/details/141896033原文链接:https://juejin.cn/post/7357554457914130467