npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vitejs-svg-plugin

v1.1.0

Published

[![npm version](https://img.shields.io/npm/v/vitejs-svg-plugin.svg)](https://www.npmjs.com/package/vitejs-svg-plugin) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Readme

vitejs-svg-plugin

npm version License: MIT

A Vite plugin that automatically loads, optimizes, and registers SVG files as inline symbols for efficient usage in your projects.

Features

  • ✅ Recursively scans SVG files from the configured directory, subdirectories included
  • ✅ Derives stable, normalized icon IDs from the file path (menu/add.svg#icon_menu-add)
  • ✅ Warns about duplicate or case-conflicting icon names without breaking the build
  • ✅ Optimizes SVGs using SVGO for smaller file sizes
  • ✅ Supports configurable ID prefix for SVG symbols
  • ✅ Sets fill="currentColor" and removes hardcoded colors so icons follow the parent color
  • ✅ Removes width/height attributes for flexible sizing
  • ✅ Registers SVGs as inline symbols in the DOM for efficient rendering
  • ✅ Emits the icon payload as a dedicated svg-icons chunk
  • ✅ Generates TypeScript type definitions for SVG icon names
  • ✅ Supports CSS mode for using SVGs as URL-encoded CSS data URIs
  • ✅ Watches the icon directory during dev and reloads automatically — no restart needed
  • ✅ Works with Vite 3, 4, 5, 6, and 7

Installation

npm install vitejs-svg-plugin --save-dev

Or using pnpm:

pnpm add -D vitejs-svg-plugin

Usage

Basic Configuration

Add the plugin to your vite.config.ts:

import { defineConfig } from 'vite'
import { createSvgLoader } from 'vitejs-svg-plugin'

export default defineConfig({
  plugins: [
    createSvgLoader({
      path: 'src/assets/svg'
    })
  ]
})

Advanced Configuration

import { defineConfig } from 'vite'
import { createSvgLoader } from 'vitejs-svg-plugin'

export default defineConfig({
  plugins: [
    createSvgLoader({
      path: 'src/assets/svg',
      prefix: 'icon', // Default: 'icon'
      css: false, // Default: false
      output: 'src/types/svg-icons.d.ts',
      entry: 'src/main.ts', // Default: auto-detected
      recursive: true, // Default: true
      keepOriginalColor: false // Default: false
    })
  ]
})

Entry Injection

The plugin injects import 'virtual:svg-loader' into your entry file, which registers the icons. By default the entry is auto-detected (see the entry option). If auto-detection cannot find an entry, or if you set entry: false, add the import manually:

// src/main.ts
import 'virtual:svg-loader'

Usage in Components

Once the loader is imported, you can use SVG icons in your components:

Vue:

<template>
  <svg class="icon">
    <use :xlink:href="'#icon_home'" />
  </svg>
</template>

React:

const Icon = ({ name }: { name: string }) => (
  <svg className="icon">
    <use xlinkHref={`#icon_${name}`} />
  </svg>
)

Configuration Options

path (required)

Type: string

The directory path where your SVG files are located, resolved relative to Vite's config.root. The plugin scans this directory for .svg files, and by default it also scans every subdirectory.

path: 'src/assets/icons'

prefix (optional)

Type: string
Default: 'icon'

The prefix to use for SVG symbol IDs, joined with _. This helps avoid ID conflicts when multiple SVG plugins are used.

prefix: 'my-icon' // Results in IDs like: my-icon_home, my-icon_menu-add

css (optional)

Type: boolean
Default: false

Enable CSS mode to use SVGs as CSS masks. When enabled, the plugin generates CSS classes with URL-encoded data URIs instead of SVG symbols.

css: true

CSS Mode Usage:

.icon-home {
  ...
}

.icon-user {
  ...
}
<template>
  <div class="icon-home"></div>
  <div class="icon-user"></div>
</template>

output (optional)

Type: string

Path to generate a TypeScript file containing icon names. This enables type-safe icon usage. Missing parent directories are created automatically, and the file is rewritten whenever the icon set changes (including while the dev server is running).

output: 'src/types/svg-icons.d.ts'

Generated file example:

/**
 * Svg Icon names (vitejs-svg-plugin)
 * @author SinJay Xie
 * @date 6/23/2026, 11:25:22 AM
 * @description Load SVG amount: 2
 */
export type SvgIconNames = 'add' | 'add2' | (string & {});

entry (optional)

Type: string | RegExp | string[] | false

The entry file(s) that should receive import 'virtual:svg-loader':

  • string: a path relative to the project root (config.root)
  • RegExp: matched against module IDs
  • string[]: any of the listed paths
  • false: disables automatic injection — add import 'virtual:svg-loader' manually

When entry is not configured, the plugin probes for an entry in this order: build.rollupOptions.input (JS/TS entries) → the <script src> in the root index.html. Injection is skipped automatically for library builds (build.lib) and SSR builds. If nothing is detected, the plugin logs a warning suggesting entry or a manual import 'virtual:svg-loader'.

entry: 'src/app.ts'

recursive (optional)

Type: boolean
Default: true

Recursively scan all subdirectories of path. Set to false to scan only the top level, which matches the legacy behavior.

recursive: false

keepOriginalColor (optional)

Type: boolean
Default: false

By default the plugin removes hardcoded fill/stroke from icon child elements (both attributes and inline style) so the icon color is fully controlled by currentColor — set color on any ancestor to recolor the icon. fill="none" and fill="currentColor" are always preserved. Set this option to true to keep the original colors.

keepOriginalColor: true

svgoOptions (optional)

Type: svgo Config

Overrides for the SVGO pipeline. By default the plugin runs preset-default plus its own plugins (remove width/height, inject fill="currentColor" and the symbol id) and always keeps viewBox. When you provide plugins, your list is used as-is instead of the default plugins.

createSvgLoader({
  path: 'src/assets/svg',
  svgoOptions: {
    // This list replaces the default plugin list
    plugins: [
      'preset-default',
      { name: 'removeAttrs', params: { attrs: ['width', 'height'] } },
      { name: 'addAttributesToSVGElement', params: { attribute: { fill: 'currentColor' } } }
    ]
  }
})

How It Works

Icon IDs

An icon ID is the file path relative to path, without the extension, joined with -, and prefixed with ${prefix}_:

  • add.svg#icon_add
  • menu/add.svg#icon_menu-add

Whitespace and the characters # % & " ' < > = / \ ( ) are replaced with -, and consecutive - are collapsed, so my icon (1).svg becomes #icon_my-icon-1. Files that resolve to the same ID (including names that differ only by case) trigger a warning, and the first icon in the sorted order is kept.

Default Mode (SVG Symbols)

  1. Scan: The plugin recursively scans the specified directory for all .svg files and derives normalized IDs
  2. Optimize: Each SVG is optimized using SVGO with preset-default plus plugins that:
    • remove width/height attributes for flexible sizing
    • inject fill="currentColor" and the symbol id
    • remove hardcoded child fill/stroke colors (unless keepOriginalColor: true)
    • keep viewBox so icons stay scalable
  3. Convert: SVG elements are converted to <symbol> elements
  4. Register: Symbols are injected into the DOM as a hidden SVG container (skipped when document is unavailable)
  5. Use: You can reference any SVG using <use xlink:href="#prefix_name" />

CSS Mode

When css: true is enabled:

  1. Scan: The plugin recursively scans the specified directory for all .svg files
  2. Optimize: Each SVG is optimized using SVGO with datauri: 'enc', producing a URL-encoded data:image/svg+xml,... payload
  3. Generate CSS: Creates CSS classes (e.g. .icon-home) that apply the SVG through CSS variables and masks, colored by currentColor
  4. Use: Apply CSS classes to elements to display SVG icons

Development

While the dev server is running, the plugin watches the icon directory. Adding, deleting, or modifying an SVG file triggers a re-scan and a page reload, and the file specified by output is updated at the same time — no restart required. The same re-scan happens in vite build --watch mode.

Example Project Structure

src/
├── assets/
│   └── svg/
│       ├── home.svg
│       ├── user.svg
│       └── menu/
│           └── add.svg
├── components/
│   └── Icon.vue
└── main.ts

This produces the IDs #icon_home, #icon_user, and #icon_menu-add.

TypeScript Support

When using the output option, the plugin generates type definitions that allow you to:

  • Get autocomplete for icon names
  • Use the generated SvgIconNames type for type-safe icon usage
  • Still pass any string (the type ends with (string & {}), so string does not collapse the union)

Example with TypeScript:

import type { SvgIconNames } from '@/types/svg-icons'

// Type-safe icon usage with autocomplete
const icon: SvgIconNames = 'home'

// Arbitrary strings are still allowed
const custom: SvgIconNames = 'home-custom'

When no icons are found, the generated type is string & {}.

License

MIT © sinjayxie