Как настроить использование svg файла в sveltekit?
Чтобы импортировать и использовать файл svg в sveltekit, я обращаюсь к этой статье https://riez.medium.com/svelte-kit-importing-svg-as-svelte-component-781903fef4ae Кстати, когда я наконец ввожу код
<svelte:component this={Logo} />
Я получил ошибку, как показано ниже
<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
Желаю, чтобы кто-нибудь помог мне с этой проблемой.
4 ответа
Проблема
Я знаю, что это старый вопрос, но, к сожалению, я тоже сталкиваюсь с той же ошибкой, и ответ здесь не очень помогает.
- используя
<img>
отлично, если стили svg являются автономными, но как только вам нужно будет изменить их размер или цвет относительно родительского элемента (например, перестанет работать) - Создание нового файла Svelte может быть отличным решением, но я предпочитаю, чтобы мои ресурсы находились в одной папке, как обычно.
почему?- для читабельности: // для ресурсов. и реальные компоненты с
- цели производительности: /questions/62736767/kuda-pomestit-izobrazheniya-s-pomoschyu-svelte-kit/62954162#62954162
- отнимает много времени : для добавления каждого актива: вам нужно вручную создать новый файл
.svelte
и вставьте код. это легко сделать для 2/3 значков, но что произойдет, если у вас будет 50/80+ значков? отнимает много времени.
- использовать для этого внешнюю библиотеку не обязательно,
потому что мы можем реализовать это самостоятельно, используя меньше кода и собственный код vite/svelte.
Итак, давайте сделаем это ниже
Решение
Как я уже сказал, ребята не устанавливают эту библиотеку, потому что
sveltekit
+
vite
обрабатывает это изначально легко (если вам это не нужно)
Сейчас в
lib/
создайте папку под названиемassets/
куда вы будете вставлять все свои.svg
/.png
/.jpg
(не внутриstatic/
из соображений производительности, потому что если внутриlib
Vite Bundler будет обрабатывать кеширование)допустим, мы хотим импортировать myIcon.svg:
<script>
import myIcon from "$lib/assets/myIcon.svg?raw"
</script>
{@html myIcon}
?raw
возвращает нам текст внутри файла (см. https://vitejs.dev/guide/features.html#static-assets)
вместо URL-ссылки, как это происходило раньше (для возврата ресурсов по умолчанию укажите?url
приглашать)
Как видите, используйте две строки собственного svelte-кода, чтобы все работало нормально.
это работает также, когда вы вкладываете свой SVG в другой и используетеcurrentColor
в большинстве случаев этот @html великолепен.
Но если ваши изображения поступают из ввода, не используйте @html, иначе вас могут взломать
(или используйте его, но с очищенными входными значениями)
РЕДАКТИРОВАТЬ:
- если вы хотите сделать это как библиотеку компонентов, используйте этот код для своего компонента:
<script>
export let src;
$: 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`
$: svgRoute = isSvg ? src.replace(".svg", ".svg?raw") : null; // you can also do `${src}?raw`
</script>
{#if isSvg}
{#await import(svgRoute)}
<div>loading...</div> <!-- default fallback, can be a loading spinner or anything else that the user will see while waiting for the loading -->
{:then value}
{@html value.default} <!-- the svg code will be inject here -->
{/await}
{:else}
<img src={Gsrc} /> <!-- if the src is only a normal photo then use native html `<img>`'s src attribute -->
{/if}
- если вы хотите еще больше упростить это
import myIcon from "$lib/assets/myIcon.svg?raw"
вы можете использовать другой мой ответ по этой теме
Как я могу упростить импорт при использовании SvelteKit с упаковщиком Vite, например $lib/?
поэтому, используя этот компонент, это будет так:
<script>
import Icon from "$lib/Icon.svelte"
</script>
<Icon src="$assets/foo.svg" />
<Icon src="$assets/bar.svg" />
<Icon src="$assets/hello.png" />
<div class="text-blue-500">
<Icon src="$assets/nested.svg" />
</div>
РЕДАКТИРОВАТЬ: ⚠️ исправление последней ошибки vitjs.
в последнее время вышеуказанное решение больше не будет работать при использованииnpm run build
выдав эту ошибку:
Ошибка типа: не удалось получить динамически импортированный модуль.
https://github.com/vitejs/vite/issues/11804
поэтому используйте это вместо SVG-части
<script lang="ts">
export let src: string;
$: isSvg = !!src.endsWith(".svg");
$: svgRoute = `${src}?raw`;
function fetchSvg(svgRoute: string) {
return new Promise((resolve) => {
fetch(svgRoute)
.then(response => response.text())
.then(svg => resolve(svg))
})
}
</script>
{#if isSvg}
{#await fetchSvg(svgRoute)}
<div>loading...</div>
{:then value}
{@html value}
{/await}
{:else}
<img src={Gsrc} />
{/if}
Существует плагин SvelteKit для встраивания SVG:s. Вы можете использовать плагин тремя разными способами:
- Как изящный компонент
- Как URL (например, для использования в теге img)
- В виде необработанного текста (например, для использования в {@html rawText})
В svelte-kit Исправить можно, попробовав
<img src={YourSVGComponent} />
У меня это сработало.
Просматривая статью, кажется, что она решает проблему, которой не существует, гораздо более сложным, чем необходимо.
В Svelte можно сделать
.svelte
компонент, который содержит только разметку SVG (встроенный), затем используйте
svelte:component
теги, как и с любым другим контентом.
Parent.svelte
<script>
import Circle from './Circle.svelte'
</script>
<svelte:component this={Circle} />
Circle.svelte
<svg viewbox="0 0 200 200">
<circle cx="100" cy="100" r="20"/>
</svg>
Вот REPL, показывающий, как переключаться между компонентами, в которых есть только SVG.
Вы даже можете добавить что-то к компонентам SVG, чтобы сделать их динамическими, поскольку это просто разметка, как показано в этом REPL .