还在为 SVG 烦恼?我写了个 CLI 工具,一键打包,性能拉满!(已开源)

还在为 SVG 烦恼?我写了个 CLI 工具,一键打包,性能拉满!(已开源)

作者:[King-GD]

GitHub: github.com/King-GD/svg...

NPM: www.npmjs.com/package/svg...

哈喽,各位掘友们好!作为一名前端开发者,和 SVG 打交道是家常便饭。它轻量、可缩放、还能用 CSS 控制样式,简直是图标方案的完美选择。但随着项目越来越大,SVG 图标一多,管理和使用上的"痛点"也随之而来。

最近,我就被这些痛点折磨得不轻,索性一怒之下,自己动手写了个 CLI 工具来彻底解决它们。没想到,从一个几十行的脚本开始,我最终把它打磨成了一个可以发布到 NPM 的完整开源项目:svg-quick

今天,我想和大家分享的,不仅仅是这个工具,更是从一个想法到一个开源产品的完整心路历程。

🤔 我们究竟在烦恼 SVG 的什么?

在使用 SVG 图标时,你是否也遇到过这些问题?

  1. 性能问题 :如果每个图标都作为独立的 .svg 文件请求,上百个图标就会导致上百个 HTTP 请求,这对性能是灾难性的。
  2. 打包效率 :在大型项目中,Webpack/Vite 每次构建都要实时去处理成百上千个 SVG 文件(比如用 svgr 转换),这会明显拖慢本就"弥足珍贵"的构建速度。
  3. 最终体积:将 SVG 作为 React/Vue 组件直接导入,每个图标都会被包裹一层组件的额外代码,积少成多,最终产物体积会悄悄膨胀。
  4. 灵活性差 :有时候我想在 <img> 里用,有时候想在 CSS background 里用,有时候又想给 ECharts 这类图表库用。不同的场景需要不同格式的图标,来回转换非常繁琐。

这些问题,每一个都像一根小刺,扎在日常开发的幸福感上。

💡 解决方案的进化之路

V1.0: 一个满足自己的脚本

一切始于一个简单的 Node.js 脚本。思路很直接:

  • 扫描一个指定文件夹里的所有 .svg 文件。
  • 读取每个文件的内容。
  • svgo 压缩优化。
  • 把所有优化后的 SVG 字符串,塞到一个 JS 对象里。
  • 最后生成一个 index.js 文件,导出这个大对象和几个辅助函数。

这个脚本解决了"多文件请求"和"重复优化"的问题,让我可以很方便地在项目里使用。但它的问题也很明显:路径硬编码、无法复用、每次换项目都得复制粘贴改代码。

V2.0: 走向 CLI 工具

为了让这个脚本能在任何项目中开箱即用,我决定把它改造成一个真正的命令行工具。

我引入了 yargs 来解析命令行参数,核心命令很快就成型了:

bash 复制代码
svg-quick --input ./icons --output ./dist

这比之前的脚本强大多了!我可以指定任意的输入和输出目录,它变成了一个可复用的工具。我当时觉得已经很完美了,直到我遇到了现代前端工程化的"灵魂拷问"------ Tree-shaking

V3.0: 拥抱 Tree-shaking 和专业化

我意识到,之前把所有图标都打包到一个大对象里的做法,有一个致命缺陷:

javascript 复制代码
// 之前产物的核心
export const icons = {
  user: '<svg>...',
  setting: '<svg>...',
  // ... 500 个图标
};

当我在代码里只 import 并使用 user 图标时,打包工具(Webpack/Vite)无法判断 icons 对象里其他 499 个图标是无用的,最终会导致所有图标都被打包进产物

这绝对不能忍!于是,我重构了整个工具的输出结构。

新的产物变成了这样:

javascript 复制代码
// Tree-shakeable 的产物
export const user = '<svg>...</svg>';
export const setting = '<svg>...</svg>';
// ... 每个图标都是一个独立的 const 导出

这样一来,import { user } from '...'; 就能让打包工具精确地"摇掉"所有未使用的图标,完美实现了按需打包

同时,我还增加了更多专业化的功能:

  • 多种输出模式 (--mode) : 用户可以选择只生成按需打包的版本 (treeshakeable),或者只生成全量版本 (full),甚至两者都要 (all)。
  • 类型定义 : 自动生成 .d.ts 文件,在 TypeScript 项目中提供完美的类型提示和自动补全。
  • 代码美化 : 内置 Prettier,确保生成的代码风格统一且美观。

至此,svg-quick 已经从一个自用的"小作坊"脚本,进化成了一个功能完备、设计考究的"正规军"。

🚀 正式介绍:svg-quick

现在,你可以通过 npx 轻松使用它,无需安装:

bash 复制代码
npx svg-quick --input <源目录> --output <目标目录> --mode <输出模式> 

它能为你带来什么?

  • ⚡️ 极致性能: 预构建模式,提升构建速度,减小产物体积。
  • 🌳 完美按需打包: 确保最终产物只包含你用到的图标。
  • ✨ 高度灵活性: 多种输出模式,满足任何使用场景。
  • 💻 优秀的开发体验: 统一的 API 和完整的 TypeScript 支持。
  • 🔧 强大的优化 : 内置 svgo,自动压缩优化。

产物使用示例

当使用推荐的 treeshakeable 模式生成产物后,你可以这样优雅地使用:

javascript 复制代码
// 在你的 React / Vue / Svelte 组件中
import { user, arrowLeft } from '../generated-icons';

// 'user' 和 'arrowLeft' 都是优化后的 SVG 字符串
// 你可以轻松地封装成自己的 <Icon> 组件

// React 示例:
const Icon = ({ svgString, ...props }) => (
  <span
    {...props}
    dangerouslySetInnerHTML={{ __html: svgString }}
  />
);

const App = () => (
  <div>
    <Icon svgString={user} style={{ color: 'blue' }} />
    <Icon svgString={arrowLeft} style={{ color: 'red' }} />
  </div>
);

🌟 写在最后

从一个解决自己痛点的小脚本,到一个功能完善并发布到 NPM 的开源工具,这个过程让我收获良多。最大的感悟是,"轮子"不一定要惊天动地,能解决一个真实、具体、哪怕很小的问题,它就是有价值的

svg-quick 现在已经非常稳定,如果你也曾为 SVG 的管理而烦恼,不妨试一试它。

如果你觉得这个小工具对你有帮助,欢迎给我的 GitHub 仓库点个 Star 🌟!如果你有任何想法或建议,也非常欢迎提 Issue 或 PR。

感谢阅读!

项目链接

相关推荐
imLix2 分钟前
RunLoop 实现原理
前端·ios
wayman_he_何大民8 分钟前
初始机器学习算法 - 关联分析
前端·人工智能
飞飞飞仔12 分钟前
别再瞎写提示词了!这份Claude Code优化指南让你效率提升10倍
前端·claude
刘永胜是我12 分钟前
node版本切换
前端·node.js
成小白16 分钟前
前端实现表格下拉框筛选和表头回显和删除
前端
wayman_he_何大民17 分钟前
初始机器学习算法 - 聚类分析
前端·人工智能
wycode18 分钟前
Vue2实践(3)之用component做一个动态表单(二)
前端·javascript·vue.js
用户10922571561034 分钟前
你以为的 Tailwind 并不高效,看看这些使用误区
前端
意会1 小时前
微信闪照小程序实现
前端·css·微信小程序
onejason1 小时前
《利用 Python 爬虫获取 Amazon 商品详情实战指南》
前端·后端·python