多年来,我在博客上使用过不同的图标集。目前我使用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 install或git 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 平台”的语言,而非依赖其上的其他抽象层。我很喜欢这一点。