unplugin-svg-transformer v1.0.32

unplugin-svg-transformer
Import easily your SVG. Powered by unplugin.
Designed to be a replacement of
kiwilan/nuxt-svg-transformer, a Nuxt module.
Use SVG into modern tools is not easy, especially when you want to use SVG as component. This plugin will parse your SVG files and create a cache file to import them easily with a library index file. It works with any framework with Vite/Webpack, but some components are ready-to-use for Vue, Nuxt and React. You could also create your own component for your favorite framework. Built for TypeScript, but works with JavaScript.
Note
If you want to use SVG from icon sets, you should use
unplugin-icons, a very good plugin from unplugin.unplugin-svg-transformeris only for custom SVG.
import type { SvgName } from "unplugin-svg-transformer/icons";
import { importSvg, svgList } from "unplugin-svg-transformer/icons";
const icon: SvgName = "svg-name";
const svg = await importSvg("svg-name"); // param fully typed (SvgName), string output
const list = svgList; // as Record<SvgName, () => Promise<{ default: string }>>Note
A demo is available on Stackblitz or directly on github.com/ewilan-riviere/unplugin-svg-transformer-example.
Features
- šØ unplugin: Vite, Rollup, Webpack, esbuild support
- šŖ Not a SVG loader, but a SVG transformer
- š„ Hot reloading when SVG added or removed
- šļø Index to list all SVG to import them easily
- š Seperated cache SVG files
- š Can be import into any JS / TS file
- š¦ Components ready, no import needed, SVG directly injected- Vue 3 / Nuxt 3 component
- React component
- Svelte not included, here is an example ./examples/svelte/src/lib/SvgIcon.svelte
 
- š Laravel Inertia compatible with laravel-vite-pluginas Vite plugin
- šØ Options to add or clear styleandclassglobal attributes
- 𦾠SVG typed (typescriptrequired)
Roadmap
- Add Nuxt 2 support
- Add more tests
- Add SVGO support
Install
npm i unplugin-svg-transformer -D
# or
pnpm install unplugin-svg-transformer -D
# or
yarn add unplugin-svg-transformer -D// vite.config.ts
import svgTransformer from "unplugin-svg-transformer/vite";
export default defineConfig({
  plugins: [
    svgTransformer({
      /* options */
    }),
  ],
});Examples for Vue, React and Svelte:
// rollup.config.js
import svgTransformer from "unplugin-svg-transformer/rollup";
export default {
  plugins: [
    svgTransformer({
      /* options */
    }),
  ],
};// webpack.config.js
module.exports = {
  /* ... */
  plugins: [
    require("unplugin-svg-transformer/webpack")({
      /* options */
    }),
  ],
};// nuxt.config.ts
export default defineNuxtConfig({
  buildModules: [
    "unplugin-svg-transformer/nuxt", // https://github.com/kiwilan/unplugin-svg-transformer
  ],
  svgTransformer: {
    /* options */
  },
});This module works for Nuxt 3 only
Example: live/nuxt3
// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      require("unplugin-svg-transformer/webpack")({
        /* options */
      }),
    ],
  },
};// esbuild.config.js
import { build } from "esbuild";
import svgTransformer from "unplugin-svg-transformer/esbuild";
build({
  plugins: [
    svgTransformer({
      /* options */
    }),
  ],
});Usage
unplugin-svg-transformer works with any framework with Vite/Webpack, but some components are ready-to-use for Vue and React. You could also create your own component for your favorite framework (only Javascript, TypeScript, Vue 3, React, Svelte and Nuxt 3 have been tested).
Options
Note
Nuxt 3 have some built-in options defined statically, because it uses amazing Nuxt 3 features. If ā option is available, otherwise is static.
| Name | Type | Description | Default | Nuxt | 
|---|---|---|---|---|
| cacheDir | string | SVG files will be added to cache directory. | ./node_modules/unplugin-svg-components/cache | ./.nuxt/icons | 
| fallback | string | Default SVG displayed when the SVG is not found. | <svg>...</svg> | ā | 
| global | boolean | Create icons.d.tsfile at the root of your project. | false | |
| libraryDir | string | Directory where icons.tswill be created. | ./src | ./.nuxt | 
| svgDir | string | Directory where your SVG files are located. | ./src/svg | ā ./assets/svg | 
| svg.classDefault | string[] | Add default classes to all SVG. | undefined | ā | 
| svg.clearSize | all,parent,none | Clear widthandheightattributes from SVG (can be all, just parent on<svg>or none). | none | ā | 
| svg.clearClass | all,parent,none | Clear classes from SVG (can be all, just parent on <svg>or none). | none | ā | 
| svg.clearStyle | all,parent,none | Clear inline styles from SVG (can be all, just parent on <svg>or none). | none | ā | 
| svg.currentColor | boolean | Add fill="currentColor"orstroke="currentColor"to all SVG. | false | ā | 
| svg.inlineStyleDefault | string[] | Add default inline style to all SVG. | undefined | ā | 
| svg.sizeInherit | boolean | Add inline style height: inherit; width: inherit;. | false | ā | 
| svg.title | boolean | Add title to SVG string. | false | ā | 
| useTypes | boolean | Use types, if you want to use JavaScript instead of TypeScript. | true | true | 
| warning | boolean | Trigger a warning when the SVG is not found. | false | ā | 
Add your SVG files
In plugin options, you can add a directory to watch SVG files: svgDir. By default, it's ./src/svg (for Nuxt 3, it's ./assets/svg). Just put your SVG files into this directory and they will be parsed and added to library file, icons.ts.
Note
You can use SVG nested directories, but you can't have two SVG files with the same name.
An example of svgDir directory:
āāā src
ā   āāā svg
ā   ā   āāā download.svg
ā   ā   āāā social
ā   ā   ā   āāā twitter.svg
ā   ā   āāā vite.svg
ā   āāā ...
āāā ...This example will give you this list: ['download', 'social/twitter', 'vite'].
Library file
In plugin options, you can add a directory to choose where to create library file: libraryDir. By default, it's ./src (for Nuxt 3, it's ./.nuxt). A library file will be created, icons.ts (or icons.js if useTypes is set to false), into this directory. This file will list all SVG files, used by importSvg function.
With TypeScript, SvgName type is available. And with JavaScript or TypeScript, you can use svgList and importSvg function. SVG list is updated when you add, remove or update a SVG file.
Note
A symlink of this file will be created into
unplugin-svg-transformer/icons.
An example of icons.ts file:
export type SvgName = "download" | "social/twitter" | "vite" | "default";
export const options = {...};
export const svgList: Record<SvgName, () => Promise<{ default: string }>> = {
  download: () => import(".../cache/download"),
  "social/twitter": () => import(".../cache/social/twitter"),
  vite: () => import(".../cache/vite"),
  default: () => import(".../cache/default"),
};
export async function importSvg(name: SvgName): Promise<string> {
  // ...
}
if (typeof window !== "undefined") {
  window.ust.options = options;
  window.ust.svgList = svgList;
  window.ust.importSvg = importSvg;
}Import SVG
You can easily import a SVG file with importSvg function from unplugin-svg-transformer/icons and use SvgName type (globally registered) to validate your SVG file name. svgList function list all SVG files, used by importSvg function.
import type { SvgName } from "unplugin-svg-transformer/icons";
import { importSvg, options, svgList } from "unplugin-svg-transformer/icons";
// `SvgName` type represents SVG file name
const icon: SvgName = "svg-name";
// importSvg function is async, you can use `await` or `then` method
const icon = await importSvg("svg-name");
// or
const icon = "";
importSvg("svg-name").then((svg) => {
  icon = svg;
});
const fallback = options.fallback; // All options are availableYou can use Window to access svgList and importSvg functions from ust (not SSR compatible).
const svg = await window.ust.importSvg("svg-name");Ready-to-use components
With some frameworks, you don't have to create your own component, you can use ready-to-use components.
Warning
Assure you have import
unplugin-svg-transformer/iconsintomain.tsorapp.ts(orapp.js) when you use ready-to-use components:import 'unplugin-svg-transformer/icons'(except for Nuxt). Why? Because ready-to-use components usewindowto access toimportSvgfunction (of course for Nuxt 3, you don't have to importunplugin-svg-transformer/iconsbecause component use#iconsalias).// main.ts import "unplugin-svg-transformer/icons";
- For Vue 3, you can use a plugin to register globally SvgIconcomponent withSvgTransformerPluginfromunplugin-svg-transformer/vueand useSvgIconcomponent directly. But you can just importSvgIconcomponent fromunplugin-svg-transformer/vueand useSvgIconcomponent.
- For React, you can import SvgIconcomponent fromunplugin-svg-transformer/react.
- For Nuxt 3, you have a globally registered SvgIconcomponent, you can useSvgIconcomponent directly. You have an alias to use easily icons:#icons, same asunplugin-svg-transformer/icons.
All ready-to-use components have a name prop, based on SVG file name. You can use name prop to validate SVG file name.
| Prop name | Prop type | Required | Prop description | 
|---|---|---|---|
| name | SvgName | ā | SVG file name | 
| title | string | Add titleto SVG | |
| reactive | boolean | Add watchto update SVG ifnameupdate (not available on React) | 
Create your own component
- For Svelte, no component available, you have to create your own, you can use example: ./examples/svelte/src/lib/SvgIcon.svelte.
- For vanilla JS or TS, you can import importSvgfunction fromunplugin-svg-transformer/iconsto import SVG file.
- For Vue or React, you can create your own component like with Svelte.
TypeScript or JavaScript
To use JavaScript only, set useTypes option to false, but this plugin is built for TypeScript first. You can use SvgName type to validate your SVG file name.
import type { SvgName } from "unplugin-svg-transformer/icons";
const icon: SvgName = "svg-name";If you use only JavaScript you can import your SVG with same way without type validation.
Global type
If you use Vite (with Vue, React or Svelte) or Nuxt, SvgName is globally imported by default. But if you use another bundler or vanilla JS/TS and you want to globally import SvgName, you can add global option to true in plugin options to create icons.d.ts at root of project to add SvgName globally. You might have to add include: ["icons.d.ts"] into tsconfig.json.
Note
With Vue, React and Svelte, this plugin use
vite-env.d.tsto addSvgNameglobally,globaloption is not needed (same for Nuxt).
// tsconfig.json, if you enabled `global` option.
{
  "include": ["icons.d.ts"]
}And enable global option in plugin options.
// vite.config.ts (or webpack.config.js, rollup.config.js, ...)
import svgTransformer from "unplugin-svg-transformer/vite";
export default defineConfig({
  plugins: [
    svgTransformer({
      global: true,
    }),
  ],
});Advanced examples
Vue 3
An example with Vue 3 and Vite.
You can skip SvgTransformerPlugin registration, this plugin will only load SvgIcon component globally, you can import SvgIcon component from unplugin-svg-transformer/vue and use SvgIcon component. But you have to import unplugin-svg-transformer/icons in main.ts if you want to use SvgIcon component.
// main.ts
import { createApp } from "vue";
import App from "./App.vue";
+import { SvgTransformerPlugin } from 'unplugin-svg-transformer/vue'
+import "unplugin-svg-transformer/icons";
createApp(App)
+ .use(SvgTransformerPlugin)
  .mount("#app");Inertia
An example with Laravel Jetstream (Inertia) and Vite. This example will use TypeScript, but it works with JavaScript. For TypeScript, you will have to create tsconfig.json file at root of project, here a example.
Note
This example use Vue 3, but it works with React or Svelte.
To use TypeScript, update vite.config.js to vite.config.ts and just add unplugin-svg-transformer/vite to plugins array.
Warning
Don't forget to replace
resources/js/app.jstoresources/js/app.tsintolaravel-vite-pluginoptions.
import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import vue from "@vitejs/plugin-vue";
+import svgTransformer from "unplugin-svg-transformer/vite";
export default defineConfig({
  resolve: {
    alias: {
      "@": "/resources/js",
      "~": "/",
    },
  },
  plugins: [
    laravel({
+     input: ["resources/js/app.ts"],
      ssr: "resources/js/ssr.js",
      refresh: true,
    }),
    vue({
      template: {
        transformAssetUrls: {
          base: null,
          includeAbsolute: false,
        },
      },
    }),
+   svgTransformer({
+     svgDir: "./resources/js/Svg",
+     libraryDir: "./resources/js",
+     global: true,
+   }),
  ],
});Just replace app.js to app.ts into resources/js (and root Blade file).
// app.ts
import type { DefineComponent } from "vue";
import { createApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/vue3";
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";
+import { SvgTransformerPlugin } from "unplugin-svg-transformer/vue";
+import 'unplugin-svg-transformer/icons'
createInertiaApp({
  title: (title) => `${title} - App Name`,
  resolve: (name) =>
    resolvePageComponent(
      `./Pages/${name}.vue`,
      import.meta.glob("./Pages/**/*.vue")
    ) as Promise<DefineComponent>,
  setup({ el, App, props, plugin }) {
    const app = createApp({ render: () => h(App, props) })
      .use(plugin)
+     .use(SvgTransformerPlugin);
    app.mount(el);
  },
});And you can use globally registered SvgIcon component.
<template>
  <div>
    <SvgIcon name="svg-name" />
  </div>
</template>React
An example with React and Vite.
You have to import unplugin-svg-transformer/icons only once in main.tsx (or app.tsx), you can use SvgIcon component if you import it from unplugin-svg-transformer/react.
// main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
+import { SvgIcon } from 'unplugin-svg-transformer/react'
import './index.css'
+import 'unplugin-svg-transformer/icons'
const root = document.getElementById('root') as HTMLElement
ReactDOM.createRoot(root).render(
  <React.StrictMode>
    hello
+   <SvgIcon name="svg-name" className='icon' />
  </React.StrictMode>,
)Nuxt 3
An example with Nuxt 3.
Installation on Nuxt 3 is easily with nuxt.config.ts file.
// nuxt.config.ts
import { defineNuxtConfig } from "nuxt3";
export default defineNuxtConfig({
  buildModules: [
    "unplugin-svg-transformer/nuxt", //
  ],
  svgTransformer: {
    /* options */
  },
});And you can use globally registered SvgIcon component or #icons alias.
<script setup lang="ts">
import { importSvg } from "#icons"; // `#icons` alias
const svg = ref<string>("");
importSvg("svg-name").then((icon) => {
  svg.value = icon;
});
</script>
<template>
  <div>
    <div v-html="svg" />
    <SvgIcon name="svg-name" />
  </div>
</template>Testing
pnpm testLocal
pnpm packageIn package.json:
{
  "devDependencies": {
    "unplugin-svg-transformer": "file:~/unplugin-svg-transformer.tgz"
  }
}Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
- UnJS: UnJS team for unplugin
- ewilan-riviere: author
- antfu: for the starter template,- @antfu/eslint-configand his amazing work
License
The MIT License (MIT). Please see License File for more information.
unplugin-version-src: https://img.shields.io/badge/dynamic/json?label=unplugin&query=dependencies[%27unplugin%27]&url=https://raw.githubusercontent.com/kiwilan/unplugin-svg-transformer/main/package.json&style=flat&colorA=18181B&colorB=F0DB4F
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago