icon
@nuxt/icon

Nuxt 的图标模块,包含 20 万+来自 Iconify 的即用图标。

nuxt-icon

Nuxt Icon

npm versionnpm downloadsLicenseNuxtVolta board

为您的 Nuxt 应用程序添加 200,000+ 个随时可用的图标,基于 Iconify

特性 ✨

  • 支持 Nuxt 3
  • SSR 友好
  • 通过 Iconify 支持 200,000 个开源矢量图标
  • 支持 CSS 模式 / SVG 模式
  • 自定义 SVG 支持(通过 Vue 组件,或通过本地 SVG 文件)

!NOTE 您正在查看此模块的 v1.0 版本,这是为了更好的开发体验和性能而完全重写的版本。如果您正在从 v0.6 迁移,请查看 此 PR 以获取完整的更改列表。

设置 ⛓️

运行以下命令将模块添加到您的项目

npx nuxi module add icon

就是这样,您现在可以在组件中使用 <Icon /> 了!

✨ 如果您正在使用 VS Code,您可以使用 Iconify IntelliSense 扩展,由 @antfu 提供。

手动设置

您可以手动安装模块,使用

npm i -D @nuxt/icon

更新您的 nuxt.config.ts

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ]
})

如果您安装了旧版模块 nuxt-icon,您可能需要将其从 modules 列表中移除。

用法 👌

属性

  • name (必填): 图标名称或全局组件名称
  • size: 图标大小 (默认: 1em)
  • mode: 图标渲染模式 (svgcss, 默认: css)

属性:

当使用 Iconify 中的图标时,将根据渲染模式创建一个 <span><svg> 元素,您可以赋予原生元素 所有属性

<Icon name="uil:github" style="color: black" />

TailwindCSS v4:

当使用 TailwindCSS v4 和 css 模式时,您应该在 Nuxt 的应用配置中配置 cssLayer

// ~/app.config.ts
export default defineAppConfig({
  icon: {
    mode: 'css',
    cssLayer: 'base'
  }
})

Iconify 数据集

您可以使用 https://icones.js.org 集合中的任何名称。

<Icon name="uil:github" />

它支持 i- 前缀(例如,i-uil-github)。

强烈建议使用以下命令在本地安装图标数据

npm i -D @iconify-json/collection-name

例如,要使用 uil:github 图标,请安装其集合 @iconify-json/uil。这样,图标可以在本地或您的无服务器函数中提供,这在 SSR 和客户端都更快、更可靠。

!NOTE 您可能还知道可以安装 @iconify/json 包来包含所有 iconify 图标。不建议这样做,因为它会增加您的服务器 bundle 大小和构建性能。如果您选择这样做,我们建议您明确指定所需的集合名称。

export default defineNuxtConfig({
  modules: ['@nuxt/icon'],
  icon: {
    serverBundle: {
      collections: ['uil', 'mdi'] // <!--- this
    }
  }
})

Vue 组件

name 与全局注册的组件匹配时,它将作为该组件渲染(在这种情况下,mode 将被忽略)。

<Icon name="MyComponent" />

请注意,MyComponent 需要位于 components/global/ 文件夹中(参见示例)。

!TIP 您还可以使用以下命令更改组件名称

export default defineNuxtConfig({
  icon: {
    componentName: 'NuxtIcon'
  }
})

自定义本地集合

您可以使用本地 SVG 文件创建自定义 Iconify 集合。

例如,将您的图标 SVG 文件放在您选择的文件夹下,例如 ./assets/my-icons

assets/my-icons
├── foo.svg
├── bar-outline.svg

在您的 nuxt.config.ts 中,在 icon.customCollections 中添加一个项目

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  icon: {
    customCollections: [
      {
        prefix: 'my-icon',
        dir: './assets/my-icons'
      },
    ],
  },
})

!NOTE 如果您在 Nuxt 4 中运行新 app 目录,资产目录是 './app/assets/*' 而不是 './assets/*'

然后您可以像这样使用图标

<template>
  <Icon name="my-icon:foo" />
  <Icon name="my-icon:bar-outline" />
</template>

您还可以传递一个完整的自定义 IconifyJSON 对象

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  icon: {
    customCollections: [
      {
        prefix: 'paid-icons',
        icons: {
          'nuxt': { body: '<path d="M281.44 ... />' },
        },
        width: 512,
        height: 512,
      }
    ],
  },
})

请注意,自定义本地集合要求您拥有一个服务器来提供 API。当设置 ssr: false,或当使用 nuxt generate(这等同于 ssr: false)生成静态应用时,提供者将默认为 Iconify API(它没有您的自定义图标)。如果您想使用服务器端点构建 SPA,您可以显式设置 provider: 'server'

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  ssr: false,
  icon: {
    provider: 'server', // <-- this
    customCollections: [
      {
        prefix: 'my-icon',
        dir: './assets/my-icons'
      },
    ],
  },
})

或者,如果您想完全禁用动态图标获取,只使用来自客户端打包的图标,您可以设置 provider: 'none'

export default defineNuxtConfig({
  icon: {
    provider: 'none',
    clientBundle: {
      scan: true,
      // ...or other bundle options
    },
  }
})

区分大小写的自定义集合

v1.10 之前,由于 Iconify 之前约定的限制,所有自定义图标都被规范化为 kebab-case 并发出警告。感谢 Iconify 方面的更新,从 v1.10 开始,您可以选择使用区分大小写的自定义集合并绕过规范化。

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  icon: {
    customCollections: [
      {
        prefix: 'my-icon',
        dir: './assets/my-icons',
        normalizeIconName: false, // <-- this
      },
    ],
  },
})

例如,这使得可以将 assets/my-icons/FooBar.svg 用作 my-icon:FooBar

normalizeIconName 默认为 true 以实现向后兼容,并将在未来的主要版本中翻转。有关更多上下文,请参见 #265

图标定制

要更新 <Icon /> 的默认大小(1em),请创建一个包含 icon.size 属性的 app.config.ts

使用 icon.class 属性更新 <Icon /> 的默认类(.icon),对于无头图标,请设置 icon.class: ''

您还可以定义别名,通过利用 icon.aliases 属性,使图标替换更容易。

!NOTE 请注意,运行时配置是 app.config.ts 而不是 nuxt.config.ts

// app.config.ts
export default defineAppConfig({
  icon: {
    size: '24px', // default <Icon> size applied
    class: 'icon', // default <Icon> class applied
    mode: 'css', // default <Icon> mode applied
    aliases: {
      'nuxt': 'logos:nuxt-icon',
    },
    cssLayer: 'base' // set the css layer to inject to
  }
})

图标的默认大小将为 24px,并且 nuxt 图标将可用。

<Icon name="nuxt" />

默认情况下,此模块将创建一个服务器端点 /api/_nuxt_icon/:collection 来从您的本地服务器 bundle 提供图标(您可以通过设置 icon.localApiEndpoint 为您想要的路径来覆盖默认路径)。当请求本地 bundle 中不存在的图标时,它将回退到请求官方 Iconify API。您可以通过将 icon.fallbackToApi 设置为 false 来禁用回退,或者设置您自己的 Iconify API 并将 icon.iconifyApiEndpoint 更新为您自己的 API 端点。

使用 customize 选项自定义图标

customize 选项允许您修改项目中使用的 SVG 图标的各个方面。通过此选项,您可以:

  • 更改描边宽度
  • 更改颜色
  • 更改动画持续时间
  • 更改不透明度
  • 添加额外形状

通过这些自定义选项,您可以完全控制 SVG 内容。

在组件中 您可以在组件中定义一个自定义函数,以对图标应用各种修改。

<script setup lang="ts">
// Define the customize function to modify SVG content
const customize = (content: string, name: string, prefix: string, provider: string) => {
  if (prefix !== 'tabler') return content // Ignore Prefix

  return content
    .replace(/stroke-width="[^"]*"/g, `stroke-width="2"`) // Change stroke width to 2
    .replace(/stroke="[^"]*"/g, `stroke="#FF5733"`) // Change stroke color to red
    .replace(/fill="[^"]*"/g, `fill="#FF5733"`) // Change fill color to red
    .replace(/animation-duration="[^"]*"/g, `animation-duration="1s"`) // Change animation duration to 1s (for animated icons)
    .replace(/opacity="[^"]*"/g, `opacity="0.8"`);// Change opacity to 0.8
}
</script>

<template>
  <Icon name="tabler:star" :customize="customize" />
</template>

<!-- You can also use `:customize="false"` to disabled the global customization function per-usage -->

在应用程序配置文件中

或者,您可以在 app.config.ts 文件中全局应用这些自定义。

// app.config.ts
export default defineAppConfig({
  icon: {
    customize: (content: string, name: string, prefix: string, provider: string) => {
      // ...
    },
  }
})

通过此配置,您的应用程序中的所有图标都将始终应用这些自定义。

服务器 Bundle

@nuxt/icon v1.0 起,我们引入了服务器 bundle 的概念,用于从 Nuxt 服务器端点提供图标。这使得客户端 bundle 保持精简,并能够按需加载图标,同时拥有所有动态功能来使用在构建时可能未知​​的图标。

服务器 Bundle 模式: local

此模式将把您本地安装的图标集合(例如 @iconify-json/*)打包到您的服务器 bundle 中作为动态块。集合数据将按需加载,仅当您的客户端从该集合请求图标时。

服务器 Bundle 模式: remote

@nuxt/icon v1.2 中引入,您现在可以使用 remote 服务器 bundle 从远程 CDN 提供图标。

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  icon: {
    serverBundle: 'remote',
  },
})

或者您可以指定远程提供者

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  icon: {
    serverBundle: {
      remote: 'jsdelivr', // 'unpkg' or 'github-raw', or a custom function
    }
  },
})

这将向 https://cdn.jsdelivr.net.cn/npm/@iconify-json/ph/icons.json 发出服务器请求,以在运行时获取图标,而不是将它们与服务器捆绑在一起。

在底层,它不再将 () => import('@iconify-json/ph/icons.json') 打包到您的服务器 bundle 中,而是使用类似 () => fetch('https://cdn.jsdelivr.net.cn/npm/@iconify-json/ph/icons.json').then(res => res.json()) 的代码,其中集合未内联。

当服务器 bundle 大小是问题时,例如在无服务器或 Worker 环境中,这将很有用。

服务器 Bundle 模式: auto

这是默认选项,模块将根据您的部署环境在 localremote 之间选择。local 将是首选,除非您部署到无服务器或工作器环境,例如 Vercel Edge 或 Cloudflare Workers。

外部化图标 JSON

默认情况下,Nitro 会将您本地安装的图标集合(例如 @iconify-json/*)打包到您的服务器 bundle 中作为动态块。当您有大量图标时,这可能会使您的打包过程变慢并消耗大量内存。您可以通过将 icon.serverBundle.externalizeIconsJson 设置为 true 来外部化图标 JSON 文件。

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  icon: {
    serverBundle: {
      externalizeIconsJson: true,
    }
  },
})

请注意,这将要求您的生产 Node.js 服务器能够导入 JSON 文件(请注意,截至 Node.js v22,JSON 模块仍然是实验性功能)。在最终构建中,它将包含类似 () => import('@iconify-json/ph/icons.json', { with: { type: 'json' } }) 的语句。

另请注意,在某些无服务器环境中,例如 Cloudflare Workers,它们没有动态导入,无论此选项如何,它们都将始终内联。

icon.serverBundle.remote 启用时,此选项将被忽略。

完全禁用服务器 Bundle

如果您想完全禁用服务器 bundle,您可以将 icon.serverBundle 设置为 false 并将 provider 设置为 iconify

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  icon: {
    provider: 'iconify',
    serverBundle: false,
  },
})

这将导致每次客户端请求图标时都向 Iconify API 发出请求。除非其他选项不可行,否则我们不建议这样做。

客户端 Bundle

对于您知道会经常使用的图标,您可以将它们与客户端 bundle 打包,以避免网络请求。

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  icon: {
    clientBundle: {
      // list of icons to include in the client bundle
      icons: [
        'uil:github',
        'logos:vitejs'
      ],

      // scan all components in the project and include icons 
      scan: true,

      // include all custom collections in the client bundle
      includeCustomCollections: true, 

      // guard for uncompressed bundle size, will fail the build if exceeds
      sizeLimitKb: 256,
    },
  },
})

includeCustomCollections 将把您在 icon.customCollections 中定义的所有自定义集合都包含在客户端 bundle 中。默认情况下它是禁用的,但在设置 ssr: false 时将自动启用。

扫描组件

scan 启用时,模块将扫描项目中的所有组件,并将使用的图标包含在客户端 bundle 中。这将显著减少静态已知图标所需的网络请求数量,但根据项目中使用的图标数量,也可能会增加客户端 bundle 的大小。

您还可以微调扫描目标,例如

export default defineNuxtConfig({
  modules: [
    '@nuxt/icon'
  ],
  icon: {
    clientBundle: {
      scan: {
        // note that when you specify those values, the default behavior will be overridden
        globInclude: ['components/**/*.vue', /* ... */],
        globExclude: ['node_modules', 'dist', /* ... */],
      },
    },
  },
})

!TIP 扫描依赖于静态分析,这意味着只检测字面用法。应尽可能避免动态构造图标名称。

<template>
  <!-- Avoid this -->
  <Icon :name="`carbon:${dark ? 'moon' : 'sun'}`" />

  <!-- Prefer this -->
  <Icon :name="dark ? 'carbon:moon' : 'carbon:sun'" />
</template>

渲染函数

您可以在渲染函数中使用 Icon 组件(如果您创建了一个函数式组件,这将很有用),为此您可以从 #components 导入它

import { Icon } from '#components'

请参阅 <MyIcon> 组件的示例

<script setup>
import { Icon } from '#components'

const MyIcon = h(Icon, { name: 'uil:twitter' })
</script>

<template>
  <p><MyIcon /></p>
</template>

贡献 🙏

  1. 克隆此仓库
  2. 使用 pnpm install 安装依赖项(使用 corepack enable 安装 pnpm了解更多
  3. 运行 npm run dev:prepare 以生成类型存根。
  4. 使用 npm run dev 以开发模式启动 playground

鸣谢 💌

许可证 📎

麻省理工学院许可证