This plugin makes it possible to import SVG files as Svelte components, inline SVG code or urls.
NOTE! This plugin isn't just for SvelteKit, but works for any Svelte project using Vite
yarn add --dev @poppanator/sveltekit-svg
npm install -D @poppanator/sveltekit-svg
In your vite.config.js
import { sveltekit } from '@sveltejs/kit/vite'
import svg from '@poppanator/sveltekit-svg'
/** @type {import('vite').UserConfig} */
const config = {
plugins: [
sveltekit(),
svg(options), // Options are optional
],
}
export default config
You can also pass multiple svg
transformers based on paths if you want to
apply different SVGO options for different SVGs
const config = {
plugins: [
sveltekit(),
svg({
includePaths: ['./src/lib/icons/', './src/assets/icons/'],
svgoOptions: {
multipass: true,
plugins: [
{
name: 'preset-default',
// by default svgo removes the viewBox which prevents svg icons from scaling
// not a good idea! https://github.com/svg/svgo/pull/1461
params: { overrides: { removeViewBox: false } },
},
{ name: 'removeAttrs', params: { attrs: '(fill|stroke)' } },
],
},
}),
svg({
includePaths: ['./src/lib/graphics/'],
svgoOptions: {
multipass: true,
plugins: ['preset-default'],
},
}),
],
}
Import as a Svelte component:
NOTE! It's recommended that you use the
?component
query string if you use the suggested type definition below. The reason is that Vite ships a type definition for*.svg
which states thatimport Comp from './file.svg
returns a string.So providing a default type definition for
*.svg
is in most cases causing a conflict which will lead to TSC errors when treating such an import as a Svelte component.So the best way to avoid errors, current and future, is to always use
import Comp from './file.svg?component
with the suggested type definition at the end of this file.
<script>
import Logo from "./logo.svg?component";
</script>
<Logo />
When used as a component you can also pass attributes to the SVG
<Logo width="200" />
Import as file path:
<script>
import logoUrl from "./logo.svg?url";
</script>
<img src={logoUrl} />
Import as data URL:
<script>
import logoDataUrl from "./logo.svg?dataurl";
</script>
<img src={logoDataUrl} />
In contrast to ?url
this will apply SVGO optimization/transform before the
the SVG is turned into a data URL
You can also pass the SVGO config option datauri
as value to ?dataurl
.
This will, for instance, generate an URI encoded string
<script>
import logoDataUrl from "./logo.svg?dataurl=enc";
</script>
<img src={logoDataUrl} />
Import as code:
<script>
import logo from "./logo.svg?src";
</script>
{@html logo}
interface Options {
/**
* Output type
* @default "component"
*
* `dataurl` can also take the following options, which are verbatim SVGO
* `datauri` options:
*
* - `?dataurl=base64` (default, same as `?dataurl`)
* - `?dataurl=enc` URL encoded string
* - `?datarl=unenc` Plain SVG
*/
type?: 'src' | 'url' | 'component' | 'dataurl'
/**
* Verbatim [SVGO](https://github.com/svg/svgo) options
*/
svgoOptions?: svgo.OptimizeOptions
/**
* Paths to apply the SVG plugin on. This can be useful if you want to apply
* different SVGO options/plugins on different SVGs.
*
* The paths are path prefixes and should be relative to your
* `svelte.config.js` file.
*
* @example
* ```
* {
* includePaths: ['src/assets/icons/', 'src/images/icons/']
* }
* ```
*/
includePaths?: string[]
}
According to a report Jest will have trouble
transforming .svg
files when such is imported as a Svelte component.
The solution seems to be to add a module name mapper entry in the the
jest.config.cjs
file, like so:
module.exports = {
// ... other config
moduleNameMapper: {
// ... other mappers
'^.+\\.svg$': '<rootDir>/src/lib/EmptyIcon.svelte',
},
}
where src/lib/EmptyIcon.svelte
can contain just <svg />
.
For Typescript not to complain about file.svg?component
et.al, add the
following to your application's app.d.ts
.
declare module '*.svg?component' {
import type { ComponentType, SvelteComponentTyped } from 'svelte'
import type { SVGAttributes } from 'svelte/elements'
const content: ComponentType<
SvelteComponentTyped<SVGAttributes<SVGSVGElement>>
>
export default content
}
declare module '*.svg?src' {
const content: string
export default content
}
declare module '*.svg?url' {
const content: string
export default content
}
declare module '*.svg?dataurl' {
const content: string
export default content
}
declare module '*.svg?dataurl=base64' {
const content: string
export default content
}
declare module '*.svg?dataurl=enc' {
const content: string
export default content
}
declare module '*.svg?dataurl=unenc' {
const content: string
export default content
}