Back to timeline

使用 Web Origami 轻松制作图标集

Making Icon Sets Easy With Web Origami

Jim Nielsen’s Blog·

多年来,我在博客上使用过不同的图标集。目前我使用Heroicons.

推荐方式使用它们的方法是将源代码从网站直接复制/粘贴到您的 HTML 中。这是一个非常简单的过程:

  • 前往网站
  • 搜索您想要的图标
  • 将鼠标悬停其上
  • 点击“复制 SVG"
  • 返回您的 IDE 并粘贴它

如果您使用的是 React 或 Vue,还可以安装相应的 npm 包,以便将图标作为组件导入。

但我并没有使用这两个框架中的任何一个,所以我需要原始的 SVG 文件,而目前没有npm i因此,对于那些,我必须手动挑选我想要的。

过去,我的做法是将 SVG 复制到项目中的单独文件里,例如:

src/
  icons/
    home.svg
    about.svg
    search.svg

然后我有一个用于从磁盘读取这些图标的“组件”,我在模板文件中使用它来将 SVG 内联到 HTML 中。例如:

// 某些页面模板文件
导入{图标}来自 './Icon.js'
const模板 =<div>${Icon('search.svg')}搜索

// Icon.js
导入文件系统来自 'fs'
导入路径来自 'path'
常量__dirname =/* 执行正确解析文件路径所需的操作 */导出 常量 图标= (名称) => fs.readFileSync(
  路径。加入(__dirname,'icons', name),'utf8').toString();

没问题,可以运行。从磁盘读取文件需要编写大量 Node.js 样板代码。

但更改图标有点麻烦。我必须找到新的 SVG 文件,覆盖现有的文件,重新提交到版本控制系统,等等。

我想如果我能就这样npm i heroicons并将原始 SVG 文件安装到我的node_modules文件夹,然后我就可以读取它们。但这也有其自身的权衡。例如:

  • 不同图标包中的名称各不相同,因此切换时名称无法匹配。例如,某个图标可能被命名为搜索在一个包装中,并且放大镜在另一种情况下。因此,更改集合需要遍历所有模板并更新引用。
  • 图标包通常非常大,而您只需要其中的一部分。npm i icon-pack可能会安装数百甚至数千个我不需要的图标。

因此,该项目的 npm 包并未提供原始 SVG 文件。虽然网站上有,但我希望有一种更程序化的方式来轻松获取我需要的图标。

我该如何做到这一点?

输入折纸

我正在使用Web 折纸对于我的博客,它能轻松地将我在模板中使用的图标映射到托管在 GitHub 上的 Heroicons。它不需要一个npm installgit submodule add以下是我的文件片段:

{
  home.svg: https://raw.githubusercontent.com/tailwindlabs/heroicons/refs/heads/master/optimized/24/outline/home.svg,
  about.svg: https://raw.githubusercontent.com/tailwindlabs/heroicons/refs/heads/master/optimized/24/outline/question-mark-circle.svg,
  search.svg: https://raw.githubusercontent.com/tailwindlabs/heroicons/refs/heads/master/optimized/24/outline/magnifying-glass.svg
}

如您所见,我为我的图标命名(例如搜索),然后将其指向通过 Heroicons 仓库托管在 Github 上的 SVG。Origami 负责通过网络获取图标并将其缓存在内存中。

很美,不是吗?它让我想起了导入地图您可以将裸模块说明符映射到 URL(并且Deno 的半废弃 HTTP 导入它们本身也很美)。

工作原理

Origami 将文件路径(甚至“远程”文件路径)提升为语言的一等公民,因此创建单个映射文件变得非常简单。您的代码库中的图标名称别人的来自某个集合的图标名称,无论这些图标是通过 npm 安装到磁盘上,还是通过互联网获取。

为了简化我之前的示例,我可以有一个像这样的文件icons.ori:

{
  home.svg: https://example.com/path/to/home.svg
  about.svg: https://example.com/path/to/information-circle.svg
  search.svg: https://example.com/path/to/magnifying-glass.svg
}

然后我可以在模板中这样引用这些图标:

<div>${icons.ori/home.svg} 搜索div>

轻而易举!当我想更换图标时,只需更新中的条目即可。icons.ori指向其他位置——远程或本地路径。

如果您想更进一步,还可以使用 Origami 的缓存功能:

Tree.cache(
  {
    home.svg: https://raw.github.com/path/to/home.svg
    about.svg: https://raw.github.com/path/to/information-circle.svg
    search.svg: https://raw.github.com/path/to/magnifying-glass.svg
  },
  Origami.projectRoot()/cache
)

这不会仅仅将文件缓存在内存中,而是会将它们缓存到本地文件夹,如下所示:

cache/
  home.svg
  about.svg
  search.svg

这非常酷,因为现在当我在本地运行我的网站时,我拥有一个本地缓存的 SVG 文件文件夹,可以查看和探索(对调试等很有用)。

这使得供应商管理如果我想将这些文件纳入项目的源代码管理中,这非常简单。只需运行一次该文件,它们就会立即出现在磁盘上!

这一点对我非常有吸引力。我想这是因为它的感觉非常“网络化”——就像我喜欢 Deno 中的 HTTP 导入一样。你通过 URL 声明依赖项,然后它们会通过网络获取并供代码的其余部分使用。没有包管理器作为中间人引入额外的复杂性,比如版本控制、传递性依赖、安装膨胀等问题。

Origami 的妙处在于,像这样处理图标并非该语言的“特性”,而是其表达力的自然结果。在某些框架中,这类问题往往需要专门的特性支持(这也是为什么在 React 和 Vue 等框架中,你需要专门的 npm 包来实现 Heroicons)。而 Origami 作为工具的设计方式,会引导你以类似 Web 技术(HTML/CSS/JS)的思路来构建解决方案。它帮助你直接使用"Web 平台”的语言,而非依赖其上的其他抽象层。我很喜欢这一点。


回复方式:电子邮件·长毛象·蓝天