vite-svg-loader: SVG files that import as Vue components
Vite plugin to load SVG files as Vue components
At a glance
- What is it?
- vite-svg-loader is a small Vite plugin that turns an SVG file into a Vue component, optimising it with SVGO on the way in. Every import style is available through a query suffix, so the same file can arrive as a component, a URL, a raw string or an unoptimised component, and the default can be changed per project.
- Who is it for?
- vite-svg-loader suits a Vue 3 project on Vite that keeps its icons as individual SVG files and wants to use them as components with props, while still needing a URL or a raw string in the occasional case.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 53 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One import, four different things you can get back
The core idea is a single line in a script block, with no wrapper file and no runtime component library:
<template>
<MyIcon />
</template>
<script setup>
import MyIcon from './my-icon.svg'
</script>The plugin is described as a Vite plugin to load SVG files as Vue components, using SVGO for optimization. What makes it more than a convenience is that the same file can be asked for in four different shapes depending on what you need at that call site. A plain import gives you a component, which is the default when no explicit params are provided. The ?url suffix gives you a URL, with the README showing the result as a data:image/svg+xml... string. The ?raw suffix gives you the file as a string, shown as <?xml version="1.0"?>.... And the ?component suffix explicitly asks for a component. So an icon in your sidebar is a component with props, and the same file pasted into a CSS background or sent to an API is a URL, without maintaining two copies of the asset.
Installing it and adding it to the Vite config
The install is one command, and it is a dev dependency because the plugin only runs at build time:
npm install vite-svg-loader --save-devThen it goes into the plugins array of your Vite config, alongside the Vue plugin:
import svgLoader from 'vite-svg-loader'
export default defineConfig({
plugins: [vue(), svgLoader()]
})The order in that array is not specified in the documentation, which is a small gap, but the plugin only intercepts .svg imports so it is unlikely to conflict with the Vue plugin. The package manifest shows the shape of the tool: main points at index.js, types at index.d.ts, and the runtime dependencies are only debug for logging and svgo for the optimisation. The peer dependency is vue at >=3.2.13, so the plugin assumes a Vue 3 project on a recent enough 3.2 release, and the package itself is published to npm as vite-svg-loader. The repository is small, with the plugin code in index.js and index.d.ts at the root alongside an example app, a cypress directory and a create-test-app.sh script for setting up a test application.
Changing what a plain import means
The default import behaviour is configurable, and this is the setting worth knowing about. When no explicit params are provided, SVGs are imported as Vue components by default, and this can be changed with the defaultImport config setting so that SVGs without params are imported as URLs or raw strings instead. The config is a single call:
svgLoader({
defaultImport: 'url' // or 'raw'
})The trade-off is worth stating plainly. Defaulting to component is convenient for icon libraries, where almost every asset is used as a component and a URL import would be the exception. Defaulting to url is the right choice for a project where assets are mostly referenced from stylesheets or markup, and where the occasional component use is rare enough to justify the explicit ?component suffix. The defaultImport setting only affects imports without a suffix, so the explicit forms keep working either way, which means the setting is safe to change later without hunting for call sites.
SVGO runs by default, and can be turned off per file
The optimisation step is where the plugin does its real work, and it comes with three levels of control. First, you can pass SVGO configuration straight through, and the README's example enables multipass:
svgLoader({
svgoConfig: {
multipass: true
}
})Second, you can disable SVGO entirely for the project:
svgLoader({
svgo: false
})Third, and most usefully, you can skip the optimiser for a single file with the ?skipsvgo suffix:
import IconWithoutOptimizer from './my-icon.svg?skipsvgo'
// <IconWithoutOptimizer />That per-file escape hatch exists because SVGO is opinionated. It rewrites path data, removes redundant attributes and can collapse structures that an icon relies on, and an icon that renders correctly in a design tool can look wrong after optimisation. Being able to exempt one file without disabling the whole pipeline is the difference between a plugin you can trust on a large icon set and one you cannot. The ?skipsvgo import still returns a component, so the exemption does not change how the file is used.
TypeScript needs two reference lines
If you use the loader in a Typescript project, the README says you will need to reference the type definitions inside vite-env.d.ts, and the two lines are:
/// <reference types="vite/client" />
/// <reference types="vite-svg-loader" />The first line is the standard Vite client types reference and the second is the one that teaches the editor what an SVG import resolves to. Without it, the import of an .svg file is a type error in the editor even though the build succeeds, because TypeScript has no idea what the plugin hands back at runtime. The package ships its own index.d.ts and points the types field at it, so the reference is all that is required. The example directory in the repository ships a tsconfig.json and a tsconfig.node.json, so the setup is visible in the project rather than only described in prose.
Where this plugin stops being the answer
The limits follow from the scope. The plugin is Vite-only, so a project on webpack, Parcel or a different bundler gets nothing from it, and it is Vue-only, since the documented output of the ?component suffix is a Vue component and the README says nothing about React or Svelte equivalents. A second limit is what SVGO can and cannot express. The optimisation is a general-purpose SVG optimiser, and if your assets carry attributes or structures the optimiser rewrites in a way you do not want, the options are to disable it for the project or exempt files one by one, and neither is a general solution for a heterogeneous asset set. Third, the plugin does one thing. There is no sprite generation, no symbol registry, no automatic size or colour theming beyond what you can express as Vue props on the resulting component, and no caching layer for repeated icons. Teams that need those reach for a dedicated icon pipeline, and the difference in approach is that such a pipeline treats the icon set as a build artifact with its own configuration, while vite-svg-loader treats each file as an independent import that happens to pass through an optimiser.
Maintenance and the shape of the project
The releases are 5.1.3 on 2026-09-01, 5.1.2 on 2026-08-26 and 5.1.1 on 2026-03-05, and the last push to the repository was on 2026-09-01, so the source tree matches the newest tag. The version is on a 5.x line, which for a plugin of this size means the breaking changes have been absorbed already, and the peer dependency range of vue >=3.2.13 tells you what the plugin expects of the framework side. The licence is MIT, declared in the manifest and in the LICENSE file at the root, which for a build-time plugin is the low-friction case. The testing setup is worth noting if you plan to fork: cypress is a dev dependency and there is a cypress directory with a cypress.json, a test:preview script that runs the preview server of the test app, and a create-test-app.sh script for generating a fresh application to test against. That is a browser-level test setup rather than unit tests, which fits a plugin whose output is a rendered component.
Editorial conclusion
vite-svg-loader suits a Vue 3 project on Vite that keeps its icons as individual SVG files and wants to use them as components with props, while still needing a URL or a raw string in the occasional case. It is the wrong tool if your project is not on Vite, since it is a Vite plugin and nothing else, and it is the wrong tool if you need the SVG transformed at build time in a way SVGO cannot express, because the optimisation step is the plugin's main transformation and turning it off gives you the file as it is. Verify first which Vue version you are on, since the package declares a peer dependency of vue >=3.2.13, and note that the plugin is Vue-only, since the README documents the ?component suffix as producing a Vue component and says nothing about React or Svelte.
Frequently asked questions
How do I install vite-svg-loader?
Run npm install vite-svg-loader --save-dev, then add svgLoader() to the plugins array of your Vite config alongside the Vue plugin. The plugin is a dev dependency because it only runs at build time.
How do I import an SVG as a URL instead of a component?
Add the ?url suffix to the import path, for example import iconUrl from './my-icon.svg?url', which yields a data:image/svg+xml... string. You can also change the project-wide default with the defaultImport setting set to 'url'.
How do I stop SVGO from optimising one icon?
Import that file with the ?skipsvgo suffix, for example import IconWithoutOptimizer from './my-icon.svg?skipsvgo'. The import still returns a component, only the optimisation step is skipped.
How do I use vite-svg-loader in a TypeScript project?
Reference the type definitions in vite-env.d.ts with /// <reference types="vite/client" /> and /// <reference types="vite-svg-loader" />, otherwise the editor reports an error on the SVG import even though the build succeeds.
Which Vue versions does vite-svg-loader support?
The package manifest declares a peer dependency of vue >=3.2.13, so it expects a Vue 3 project on 3.2.13 or newer.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jpkleemans-vite-svg-loader)Was this useful?