DEV Community

Cover image for The Last SVG Tool You’ll Ever Need: A Zero-Dependency Alternative to SVGR
navid rezadoost
navid rezadoost

Posted on

The Last SVG Tool You’ll Ever Need: A Zero-Dependency Alternative to SVGR

The SVG Mess We All Live In

Let’s be honest: handling SVGs in modern web development is a fragmented mess. If you're on a React project, you npm install @svgr/webpack. The moment you switch to a Vue project, you're wrestling with vite-svg-loader. Working on a Svelte app? Time to find another package.

Each tool comes with its own API, its own configuration, and—worst of all—its own mountain of transitive dependencies. A simple npm install @svgr/cli can dump over 15 packages and 18MB into your node_modules.

This isn't just about disk space. It's about:

  • Slower CI/CD pipelines
  • A larger security attack surface
  • Inconsistent workflows across your projects

We've normalized this "one tool per framework" approach, but it's an anti-pattern. It’s time for a better solution.

Introducing svger-cli: The Unified, Zero-Dependency SVG Engine

I'd like to introduce svger-cli, an open-source tool built to solve this exact problem.

The core philosophy is simple but powerful: do everything with native Node.js APIs and have zero dependencies.

That's right. Zero.

This allows svger-cli to be a single, blazing-fast binary that handles every major framework you can throw at it. It's not just a replacement for one tool; it's a replacement for all of them.

One Command, Any Framework

With svger-cli, you no longer need to remember different package names or configs. You just tell it what you want.

# Generate React components (the default)
svger-cli build ./my-svgs ./components

# Switch to Vue with Composition API
svger-cli build ./my-svgs ./components --framework vue --composition

# Or maybe Angular standalone components?
svger-cli build ./my-svgs ./components --framework angular --standalone

# How about Svelte?
svger-cli build ./my-svgs ./components --framework svelte
Enter fullscreen mode Exit fullscreen mode

It generates high-quality, idiomatic components for React, Vue, Angular, Svelte, Solid, Preact, Lit, and even Vanilla JS/TS.

What the Output Looks Like
The generated code is clean, typed, and follows framework best practices.

React (.tsx)

import React from "react";
import type { SVGProps } from "react";

export interface HomeIconProps extends SVGProps<SVGSVGElement> {
  size?: number | string;
}

const HomeIcon = React.forwardRef<SVGSVGElement, HomeIconProps>(
  ({ size, className, style, ...props }, ref) => {
    const dimensions = size ? { width: size, height: size } : {
      width: props.width || 24,
      height: props.height || 24
    };

    return (
      <svg
        ref={ref}
        viewBox="0 0 24 24"
        xmlns="http://www.w3.org/2000/svg"
        width={dimensions.width}
        height={dimensions.height}
        fill={props.fill || "currentColor"}
        className={className}
        style={style}
        {...props}
      >
        <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
      </svg>
    );
  }
);

HomeIcon.displayName = "HomeIcon";
export default HomeIcon;
Enter fullscreen mode Exit fullscreen mode

Vue 3 with Composition API (.vue)

<template>
  <svg
    :class="className"
    :style="style"
    :width="width || 24"
    :height="height || 24"
    :fill="fill || 'currentColor'"
    :stroke="stroke"
    viewBox="0 0 24 24"
    xmlns="http://www.w3.org/2000/svg"
    v-bind="$attrs"
  >
    <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
  </svg>
</template>

<script setup lang="ts">
interface Props {
  className?: string;
  style?: string | Record<string, any>;
  width?: string | number;
  height?: string | number;
  fill?: string;
  stroke?: string;
}

withDefaults(defineProps<Props>(), {
  className: '',
  fill: 'currentColor',
  width: 24,
  height: 24
});
</script>
Enter fullscreen mode Exit fullscreen mode

Svelte (.svelte)

<script lang="ts">
  export let className: string = '';
  export let style: string = '';
  export let width: string | number = 24;
  export let height: string | number = 24;
  export let fill: string = 'currentColor';
  export let stroke: string = '';
</script>

<svg
  class={className}
  {style}
  {width}
  {height}
  {fill}
  {stroke}
  viewBox="0 0 24 24"
  xmlns="http://www.w3.org/2000/svg"
  {...$$restProps}
>
  <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</svg>
Enter fullscreen mode Exit fullscreen mode

Angular Standalone (.component.ts)

import { Component, Input, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'app-home-icon',
  standalone: true,
  template: `
    <svg
      [attr.class]="className"
      [attr.width]="width"
      [attr.height]="height"
      [attr.fill]="fill"
      [attr.stroke]="stroke"
      viewBox="0 0 24 24"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
    </svg>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class HomeIconComponent {
  @Input() className: string = '';
  @Input() width: string | number = 24;
  @Input() height: string | number = 24;
  @Input() fill: string = 'currentColor';
  @Input() stroke: string = '';
}
Enter fullscreen mode Exit fullscreen mode

More Than Just a Converter: Pro-Level Features
Because svger-cli is built from the ground up, it includes features that address real-world development pains.

1. Auto-Generated Index Files
It creates and maintains an index.ts file in your output directory, so you can do this without any extra effort:

// No more manual exports!
import { HomeIcon, UserIcon, SettingsIcon, SearchIcon } from './components';
Enter fullscreen mode Exit fullscreen mode

2. File Protection System
Protect critical assets like your company logo from being accidentally overwritten during a build:

svger-cli lock ./assets/logo.svg
svger-cli unlock ./assets/logo.svg
Enter fullscreen mode Exit fullscreen mode

3. Optimized Watch Mode
A native file watcher (fs.watch) instantly recompiles components on change, with minimal overhead:

svger-cli build ./svgs ./components --watch
Enter fullscreen mode Exit fullscreen mode

4. Enterprise-Grade Configuration
Manage complex workflows with a configuration file:

{
  "framework": "vue",
  "typescript": true,
  "frameworkOptions": {
    "composition": true,
    "scriptSetup": true
  },
  "batchSize": 50,
  "parallelProcessing": true
}
Enter fullscreen mode Exit fullscreen mode

**The Performance Numbers Don't Lie
**Here's a comprehensive look at how svger-cli stacks up against the competition. The zero-dependency architecture makes a massive difference.

Real-World Benchmarks
Testing with 100 SVG files (average 2KB each) on a standard development machine:

svger-cli: 1.2 seconds (zero dependencies, native processing)

SVGR: 7.8 seconds (heavy dependency tree, multiple transforms)

vite-svg-loader: 4.3 seconds (build-time processing overhead)

Manual process: 15+ minutes (copy-paste, manual optimization)

Give It a Try in 60 Seconds
Stop bloating your projects and start simplifying your cross-framework workflows. svger-cli is open-source and ready to use.

  1. Install it globally:
npm install -g svger-cli
Enter fullscreen mode Exit fullscreen mode
  1. Or use it directly with npx:
npx svger-cli build ./svgs ./components --framework vue
Enter fullscreen mode Exit fullscreen mode
  1. Run it on your SVG folder:
svger-cli build ./path/to/svgs ./output/components --framework react --typescript
Enter fullscreen mode Exit fullscreen mode

That's it. You now have a folder of clean, performant, framework-ready components with full TypeScript support and auto-generated exports.

Perfect For These Scenarios
Design Systems that need to support multiple frameworks

Monorepos with mixed frontend technologies

Micro-frontend architectures

Agency work with diverse client tech stacks

Open-source libraries that want framework-agnostic assets

Performance-critical applications where bundle size matters

Join the Community
The project is actively maintained and growing. We welcome contributions, bug reports, and feature requests.

Check out the project on GitHub to see all the features, detailed documentation, and supported frameworks.

➡️ Get Started with SVGER-CLI on GitHub

Conclusion
In a world of framework fragmentation and dependency bloat, svger-cli offers a refreshing alternative: one tool, zero dependencies, and support for every major UI framework. It's not just about converting SVGs—it's about providing a professional, enterprise-grade workflow that scales with your needs.

Whether you're building a design system, managing a monorepo, or just tired of juggling different SVG tools, give svger-cli a try. Your node_modules folder will thank you.

Happy coding! 🚀

Top comments (0)