如何配置在 sveltekit 中使用 svg 文件?

min*_*ang 5 svg server-side-rendering svelte-component vite sveltekit

要在sveltekit中导入和使用svg文件,我参考这篇文章 https://riez.medium.com/svelte-kit-importing-svg-as-svelte-component-781903fef4ae 顺便说一句,当我最终输入代码时

<svelte:component this={Logo} />
Run Code Online (Sandbox Code Playgroud)

我收到如下错误

<svelte:component this={...}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules
Run Code Online (Sandbox Code Playgroud)

我希望有人帮助我解决这个问题。

Laa*_*nas 7

问题

\n

我知道这是一个老问题,但不幸的是,我也遇到了同样的错误,这里的答案并没有多大帮助。

\n
    \n
  1. <img>如果 svg 样式是独立的,那么使用 a非常好,但是一旦您需要相对于父元素调整它们的大小或颜色(像currentColor这样就停止工作)
  2. \n
  3. 创建一个新的 Svelte 文件可能很棒,但我更喜欢我的资源像平常一样位于一个文件夹中。\n
    为什么?\n
      \n
    • 出于可读目的: .svg //.png用于.jpg资产。和真实的组件.svelte
    • \n
    • 性能目的: /sf/answers/5263420151/
    • \n
    • 耗时:对于每个资产都必须添加:您需要手动创建一个新文件.svelte,并粘贴.svg代码。这对于 2/3 的图标来说很容易,但如果你有 50/80+ 的图标会怎样?很费时间。
    • \n
    \n
  4. \n
  5. 没有必要使用外部库,
    因为我们可以使用更少的代码和本机 vite/svelte 代码自己实现这一点。\n

    所以让我们在下面这样做
  6. \n
\n
\n

解决方案

\n

正如我所说,人们不会安装该库,因为sveltekit+vite它本身就可以轻松处理(除非您需要)

\n
    \n
  1. 现在lib/创建一个名为的文件夹,assets/您将在其中插入所有内容.svg// .png(出于性能原因.jpg不在里面,因为如果在里面vite 捆绑程序将处理缓存)static/lib

    \n
  2. \n
  3. 假设我们要导入 myIcon.svg:

    \n
  4. \n
\n
<script>\n  import myIcon from "$lib/assets/myIcon.svg?raw"\n</script>\n\n{@html myIcon}\n
Run Code Online (Sandbox Code Playgroud)\n

?raw正在向我们返回文件内的文本(请参阅https://vitejs.dev/guide/features.html#static-assets)\n
而不是 URL 链接,就像之前发生的那样(对于默认资产返回有?urlvite )

\n

如您所见,使用 2 行本机简洁代码即可使其正常工作。

\n

当您将 svg 嵌套在另一个 svg 中并且您正在使用时,这也适用currentColor

\n
\n

在大多数情况下,这个@html很棒,\n
但是如果你的图像来自输入,那么不要使用@html,否则你可能会被黑客攻击\n
(或者使用它,但输入值已清理)

\n
\n
\n

编辑:

\n
    \n
  • 如果您想使其像组件库一样,请为您的组件使用此代码:
  • \n
\n
<script>\n  export let src;\n\n  $: isSvg = !!src.endsWith(".svg");                             // we use $: because you may dynamically change the src so the component needs to be reactive. if you are sure that it won\'t be changed it will be great to use instead `const`\n  $: svgRoute = isSvg ? src.replace(".svg", ".svg?raw") : null;  // you can also do `${src}?raw`\n</script>\n\n{#if isSvg}\n  {#await import(svgRoute)}\n    <div>loading...</div>       <!-- default fallback, can be a loading spinner or anything else that the user will see while waiting for the loading -->\n  {:then value}\n    {@html value.default}       <!-- the svg code will be inject here -->\n  {/await}\n{:else}\n  <img src={Gsrc} />            <!-- if the src is only a normal photo then use native html `<img>`\'s src attribute -->\n{/if}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 如果您想进一步简化,import myIcon from "$lib/assets/myIcon.svg?raw"您可以使用我关于该主题的其他答案
  • \n
\n

在将 SvelteKit 与 Vite 捆绑器(如 $lib/)一起使用时,如何简化导入?

\n

所以通过使用该组件,它会像这样:

\n
<script>\n  import Icon from "$lib/Icon.svelte"\n</script>\n\n<Icon src="$assets/foo.svg" />\n<Icon src="$assets/bar.svg" />\n<Icon src="$assets/hello.png" />\n\n<div class="text-blue-500">\n  <Icon src="$assets/nested.svg" />\n</div>\n
Run Code Online (Sandbox Code Playgroud)\n
\n

编辑:\xe2\x9a\xa0\xef\xb8\x8f 修复最新 vitejs\ 的错误

\n

npm run build最近,当使用抛出此错误时,上述解决方案将不再起作用:

\n
\n

类型错误:无法获取动态导入的模块

\n
\n

https://github.com/vitejs/vite/issues/11804

\n

所以用它来代替 svg 部分

\n
<script>\n  import myIcon from "$lib/assets/myIcon.svg?raw"\n</script>\n\n{@html myIcon}\n
Run Code Online (Sandbox Code Playgroud)\n


小智 6

有一个用于内联 SVG:s 的 SvelteKit 插件。您可以通过三种不同的方式使用该插件:

  1. 作为一个 Svelte 组件
  2. 作为 URL(例如在 img 标签中使用)
  3. 作为原始文本(例如在 {@html rawText} 中使用)

https://www.npmjs.com/package/@poppanator/sveltekit-svg


JHe*_*eth 3

浏览这篇文章,它似乎正在以一种比需要的更复杂的方式解决一个不存在的问题。

在 Svelte 中,您可以创建一个.svelte仅包含 SVG 标记(内联)的组件,然后svelte:component像处理任何其他内容一样使用该标记。

父母.svelte

<script>
  import Circle from './Circle.svelte'
</script>

<svelte:component this={Circle} />
Run Code Online (Sandbox Code Playgroud)

圆细

<svg viewbox="0 0 200 200">
  <circle cx="100" cy="100" r="20"/>
</svg>
Run Code Online (Sandbox Code Playgroud)

这是一个REPL,展示了如何在仅包含 SVG 的组件之间进行切换。

您甚至可以向 SVG 组件添加内容以使它们动态,因为它只是像 REPL 中所示的标记