通过 VSCode Webview API 提供 SvelteKit 应用程序

Orb*_*iox 7 javascript visual-studio-code vscode-extensions svelte sveltekit

在花了数周时间并多次放弃尝试解决此问题后,才提出这个问题。

我正在开发一个 VSCode 扩展,需要使用Webview API。有一段时间,这可能是使用 Svelte,但现在 SvelteKit 已稳定发布,并且在您使用时被视为默认值npm create svelte,我的目标是使用它。将应用程序配置为静态 SPA 并关闭 SSR 并使用 后@sveltejs/adapter-static,似乎提供的服务与使用 vanilla Svelte 的服务不同。

这是svelte.config.js

import adapter from '@sveltejs/adapter-static';
import preprocess from 'svelte-preprocess';

/**
 * Consult https://github.com/sveltejs/svelte-preprocess
 * for more information about preprocessors
 *
 * @type {import('@sveltejs/kit').Config} */
export default {
  preprocess: preprocess(),
  kit: {
    adapter: adapter({ fallback: 'index.html' }),
    // ssr: false, // deprecated
    csp: {
      directives: {
        'default-src': ['none'],
        'img-src': ['{{cspSource}} https:'],
        'script-src': ['{{cspSource}}'],
        'style-src': ['{{cspSource}}'],
      },
    },
    // paths: {
    //   base: '{{baseURL}}', // not accepted
    // },
  },
};
Run Code Online (Sandbox Code Playgroud)

这是构建的 HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="/favicon.png" />
    <meta name="viewport" content="width=device-width" />
    <meta http-equiv="content-security-policy" content="default-src 'none'; img-src {{cspSource}} https:; script-src {{cspSource}} 'sha256-N2DRY+AREasGSTE5X4BdHoEYZsaGOpTvUwTBIHmryVA='; style-src {{cspSource}}">
        <link rel="modulepreload" href="/_app/immutable/start-e16b6a0f.js">
        <link rel="modulepreload" href="/_app/immutable/chunks/index-0576dc7c.js">
        <link rel="modulepreload" href="/_app/immutable/chunks/singletons-51070258.js">
  </head>
  <body data-sveltekit-preload-data="hover">
    <div style="display: contents">
        <script type="module" data-sveltekit-hydrate="45h">
            import { start } from "/_app/immutable/start-e16b6a0f.js";

            start({
                env: {},
                paths: {"base":"","assets":""},
                target: document.querySelector('[data-sveltekit-hydrate="45h"]').parentNode,
                version: "1672682689612"
            });
        </script></div>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

与 vanilla Svelte 相反,它会生成如下内容:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="/favicon.png" />
    <meta name="viewport" content="width=device-width" />
    <script src="/dist/app/main.js"></script>
  </head>
  <body>
   <div id="app"></div>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

可以通过 Webview 提供服务,例如:

function getWebviewContent(webview, context) {
    return `
    <!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'",
          `img-src ${webview.cspSource} https:`,
          `script-src ${webview.cspSource}`,
          `style-src ${webview.cspSource}`,
        ].join(';')};"
            />
      <title>My Extension</title>
            <script type="module" crossorigin src="${webview.asWebviewUri(
        vscode.Uri.joinPath(context.extensionUri, 'dist/app/main.js')
      )}"></script>
            <link rel="stylesheet" href="${webview.asWebviewUri(
        vscode.Uri.joinPath(context.extensionUri, 'dist/app/style.css')
      )}">
        </head>
        <body><div id="app"></div></body>
    </html>
  `;
}
Run Code Online (Sandbox Code Playgroud)

该文件现在有点复杂,所以我不能(也不应该)尝试在此函数中重写它。

以下是条件:

  1. VSCode 需要绝对路径,因为它有不同的环境和协议。请记住,扩展是在本地为每个用户提供服务的。(context.extensionUri很重要)
  2. SvelteKit 有其一组配置(与 Vite 不同),这些配置可能会特别限制 SPA 模式。
  3. Webview 的内容安全策略还限制了哪些内容可以使用以及哪些内容不能使用。
  4. 可能是由于 Vite,文件名具有哈希值,因此不一致 - 但我更愿意保留它。
  5. HTML 中的脚本块(可能还需要一个nonce)将start函数作为模块相对导入。
  6. 最好将生成的 HTML 读入 VSCode 并提供服务,而不是编写另一个模板作为需要维护的 VSCode 字符串。使用Mustache似乎不错(因此您可以{{cspSource}}在上面的 HTML 中看到)。

人们会如何建议构建和集成这一点?