unplugin-icons
通用地按需访问数千个图标组件。
特性
- 🌏 通用
- ☁️ 按需加载 - 只打包你真正使用的图标,同时保留所有选项。
- 🖨 SSR / SSG 友好 - 将图标与页面一起发送,不再出现FOUC。
- 🌈 可样式化 - 像使用样式和类一样更改大小、颜色,甚至添加动画。
- 📥 自定义图标 - 轻松加载自定义图标以获得通用集成。
- 📲 自动导入 - 直接在模板中使用图标作为组件。
- 🦾 TypeScript支持。
- 🔍 浏览图标
💡 这个工具背后的故事: 与图标的旅程继续 - Anthony的博客文章 |
vite-plugin-icons
已更名为unplugin-icons
,请参阅迁移指南
使用方法
使用~icons/{collection}/{icon}
约定导入图标名称,并直接将它们作为组件使用。也可以自动导入。
React
import IconAccessibility from '~icons/carbon/accessibility'
import IconAccountBox from '~icons/mdi/account-box'
function App() {
return (
<div>
<IconAccessibility />
<IconAccountBox style={{ fontSize: '2em', color: 'red' }} />
</div>
)
}
Vue
<script setup>
import IconAccessibility from '~icons/carbon/accessibility'
import IconAccountBox from '~icons/mdi/account-box'
</script>
<template>
<icon-accessibility/>
<icon-account-box style="font-size: 2em; color: red"/>
</template>
安装
插件
npm i -D unplugin-icons
图标数据
我们使用Iconify作为图标数据源(支持100多个图标集)。
你有两种安装方式:
安装完整集合
npm i -D @iconify/json
@iconify/json
(约120MB)包含了Iconify的所有图标集,所以你可以一次安装并按需使用任何图标(只有你实际使用的图标会被打包到生产构建中)。
按图标集安装
如果你只想使用少数几个图标集,不想下载整个集合,你也可以使用@iconify-json/[collection-id]
单独安装它们。
例如,要安装Material Design Icons,你可以执行:
npm i -D @iconify-json/mdi
为了提高工作效率,你也可以通过启用autoInstall
选项让unplugin-icons
处理安装。
Icons({
// 实验性功能
autoInstall: true,
})
它会在你导入图标时安装图标集。会自动检测正确的包管理器(npm
、yarn
或pnpm
)。
示例
你可以在StackBlitz上在线试用此仓库中的示例,请参阅playground页面。
复制任何在线示例并重现你遇到的问题,然后与我们分享链接。
配置
构建工具
Vite
// vite.config.ts
import Icons from 'unplugin-icons/vite'
export default defineConfig({
plugins: [
Icons({ /* 选项 */ }),
],
})
Rollup
// rollup.config.js
import Icons from 'unplugin-icons/rollup'
export default {
plugins: [
Icons({ /* 选项 */ }),
],
}
Webpack
// webpack.config.js
module.exports = {
/* ... */
plugins: [
require('unplugin-icons/webpack').default({ /* 选项 */ }),
],
}
Nuxt
Nuxt 2和Nuxt Bridge
// nuxt.config.js
export default {
buildModules: [
['unplugin-icons/nuxt', { /* 选项 */ }],
],
}
Nuxt 3
// nuxt.config.js
export default defineNuxtConfig({
modules: [
['unplugin-icons/nuxt', { /* 选项 */ }]
],
})
或与unplugin-vue-components解析器一起使用
import ViteComponents from 'unplugin-vue-components/vite'
import IconsResolver from 'unplugin-icons/resolver'
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
'unplugin-icons/nuxt',
],
vite: {
plugins: [
ViteComponents({
resolvers: [
IconsResolver({/* 选项 */}),
],
}),
],
},
})
查看Nuxt示例以获取工作示例项目。
Vue CLI
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
require('unplugin-icons/webpack').default({ /* 选项 */ }),
],
},
}
你也可以将Vue配置文件重命名为vue.config.mjs
并使用静态导入语法(你应该使用最新的@vue/cli-service ^5.0.8
):
// vue.config.mjs
import Icons from 'unplugin-icons/webpack'
export default {
configureWebpack: {
plugins: [
Icons({ /* 选项 */ }),
],
},
}
SvelteKit
unplugin-icons
插件应该在vite.config.js
配置文件中配置:
// vite.config.js
import { defineConfig } from 'vite'
import { sveltekit } from '@sveltejs/kit/vite'
import Icons from 'unplugin-icons/vite'
export default defineConfig({
plugins: [
sveltekit(),
Icons({
compiler: 'svelte',
})
]
})
如果遇到模块导入错误,请查看下面框架 -> Svelte
部分的说明。
查看SvelteKit示例以获取工作示例项目。
Svelte + Vite
Svelte支持需要@sveltejs/vite-plugin-svelte
插件:
npm i -D @sveltejs/vite-plugin-svelte
unplugin-icons
插件应该在vite.config.js
配置文件中配置:
// vite.config.js
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import Icons from 'unplugin-icons/vite'
export default defineConfig({
plugins: [
svelte(),
Icons({
compiler: 'svelte',
}),
],
})
如果遇到模块导入错误,请查看下面框架 -> Svelte
部分的说明。
查看Svelte + Vite示例以获取工作示例项目。
Next.js
`unplugin-icons` 插件应该在 `next.config.js` 配置文件中进行配置:
// next.config.js
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
webpack(config) {
config.plugins.push(
require('unplugin-icons/webpack').default({
compiler: 'jsx',
jsx: 'react'
})
)
return config
},
}
你也可以将 Next 配置文件重命名为 next.config.mjs
并使用静态导入语法:
// next.config.mjs
import Icons from 'unplugin-icons/webpack'
/** @type {import('next').NextConfig} */
export default {
reactStrictMode: true,
webpack(config) {
config.plugins.push(
Icons({
compiler: 'jsx',
jsx: 'react'
})
)
return config
}
}
如果遇到模块导入错误,请查看下面 框架 -> React
部分的说明。
⚠️ 警告: 导入图标时必须在导入路径中明确添加 .jsx
扩展名,以便 Next.js 知道如何加载它,例如:
import IconArrowRight from '~icons/dashicons/arrow-right.jsx';
// ^-- 写上 `.jsx` 以避免
// https://github.com/antfu/unplugin-icons/issues/103
// ...后续代码
<IconArrowRight />
查看 Next.js 示例 获取一个可运行的示例项目。
esbuild
// esbuild.config.js
import { build } from 'esbuild'
import Icons from 'unplugin-icons/esbuild'
build({
/* ... */
plugins: [
Icons({
/* 选项 */
}),
],
})
Astro
// astro.config.mjs
import { defineConfig } from 'astro/config'
import Icons from 'unplugin-icons/vite'
// https://astro.build/config
export default defineConfig({
vite: {
plugins: [
Icons({
compiler: 'astro',
}),
],
},
})
查看 Astro 示例 获取一个可运行的示例项目。
Astro + Vue
需要安装 @astrojs/vue。
// astro.config.mjs
import { defineConfig } from 'astro/config'
import Vue from '@astrojs/vue'
import Icons from 'unplugin-icons/vite'
// https://astro.build/config
export default defineConfig({
integrations: [
Vue(),
],
vite: {
plugins: [
Icons({
compiler: 'vue3',
}),
],
},
})
查看 Astro + Vue 示例 获取一个可运行的示例项目。
框架
Vue 3 / Vue 2.7+
Vue 3 / Vue 2.7+ 支持需要对等依赖 @vue/compiler-sfc
:
npm i -D @vue/compiler-sfc
Icons({ compiler: 'vue3' })
类型声明
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/vue",
]
}
}
查看 Vue 3 示例 获取一个可运行的示例项目。
Vue 2(仅适用于 2.7 以下版本)
Vue 2 支持需要对等依赖 vue-template-compiler
:
npm i -D vue-template-compiler
Icons({ compiler: 'vue2' })
类型声明
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/vue",
]
}
}
查看 Vue 2 示例 获取一个可运行的示例项目。
React
JSX 支持需要对等依赖 @svgr/core
及其插件 @svgr/plugin-jsx
:
npm i -D @svgr/core @svgr/plugin-jsx
Icons({ compiler: 'jsx', jsx: 'react' })
类型声明
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/react",
]
}
}
查看 React 示例 获取一个可运行的示例项目。
Preact
JSX 支持需要对等依赖 @svgr/core
及其插件 @svgr/plugin-jsx
:
npm i -D @svgr/core @svgr/plugin-jsx
Icons({ compiler: 'jsx', jsx: 'preact' })
类型声明
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/preact",
]
}
}
查看 Preact 示例 获取一个可运行的示例项目。
Solid
Icons({ compiler: 'solid' })
类型声明
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/solid",
]
}
}
查看 Solid 示例 获取一个可运行的示例项目。
Svelte
Icons({ compiler: 'svelte' })
类型声明
对于 SvelteKit,在 src/app.d.ts
文件中:
import 'unplugin-icons/types/svelte'
对于 Svelte + Vite,在 src/vite-env.d.ts
文件中:
/// <reference types="svelte" />
/// <reference types="vite/client" />
/// <reference types="unplugin-icons/types/svelte" />
如果你仍在使用 Svelte 3,请将引用替换为 Svelte 3:
/// <reference types="svelte" />
/// <reference types="vite/client" />
/// <reference types="unplugin-icons/types/svelte3" />
查看 Svelte 示例 获取一个可运行的示例项目。
Astro
类型声明
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/astro",
]
}
}
查看 Astro 示例 获取一个可运行的示例项目。
Astro + Vue
只需要 Vue 类型声明:
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/vue"
]
}
}
查看 Astro + Vue 示例 获取一个可运行的示例项目。
Qwik
Qwik 支持需要对等依赖 @svgx/core
:
npm i -D @svgx/core
Icons({ compiler: 'qwik' })
或者,你可以使用 jsx
编译器,需要对等依赖 @svgr/core
及其插件 @svgr/plugin-jsx
:
npm i -D @svgr/core @svgr/plugin-jsx
Icons({ compiler: 'jsx', jsx: 'qwik' })
类型声明
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/qwik",
]
}
}
查看 Qwik 示例 获取一个可运行的示例项目。
从查询参数使用 RAW 编译器
从 v0.13.2
开始,你还可以使用 raw
编译器来访问 svg
图标并在 HTML 模板中使用它,只需在图标查询参数中添加 raw
。
例如,使用 vue3
:
<script setup lang='ts'>
import RawMdiAlarmOff from '~icons/mdi/alarm-off?raw&width=4em&height=4em'
import RawMdiAlarmOff2 from '~icons/mdi/alarm-off?raw&width=1em&height=1em'
</script>
<template>
<!-- 原始示例 -->
<pre>
import RawMdiAlarmOff from '~icons/mdi/alarm-off?raw&width=4em&height=4em'
{{ RawMdiAlarmOff }}
import RawMdiAlarmOff2 from '~icons/mdi/alarm-off?raw&width=1em&height=1em'
{{ RawMdiAlarmOff2 }}
</pre>
<!-- svg 示例 -->
<span v-html="RawMdiAlarmOff" />
<span v-html="RawMdiAlarmOff2" />
</template>
自定义图标
从 v0.11
开始,你现在可以加载自己的图标!
从 v0.13
开始,你还可以为 FileSystemIconLoader
提供一个转换回调函数。
import { promises as fs } from 'node:fs'
// 加载器辅助函数
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
Icons({
customCollections: {
// 键作为集合名称
'my-icons': {
account: '<svg><!-- ... --></svg>',
// 懒加载你的自定义图标
settings: () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),
/* ... */
},
'my-other-icons': async (iconName) => {
// 你的自定义加载器。可以做任何你想做的事。
// 例如,从远程服务器获取:
return await fetch(`https://example.com/icons/${iconName}.svg`).then(res => res.text())
},
// 一个从文件系统加载图标的辅助函数
// `./assets/icons` 下带 `.svg` 扩展名的文件将按其文件名加载
// 你还可以提供一个转换回调函数来改变每个图标(可选)
'my-yet-other-icons': FileSystemIconLoader(
'./assets/icons',
svg => svg.replace(/^<svg /, '<svg fill="currentColor" '),
),
},
})
然后这样使用
import IconAccount from '~icons/my-icons/account'
import IconFoo from '~icons/my-other-icons/foo'
import IconBar from '~icons/my-yet-other-icons/bar'
💡 SVG 创作提示:
- 要使你的图标颜色可适应,在你的 SVG 中设置
fill="currentColor"
或stroke="currentColor"
。- 不要指定
height
和width
,我们会为你设置它们。
与解析器一起使用
当使用解析器进行自动导入时,你需要告诉它你的自定义集合名称:
IconResolver({
customCollections: [
'my-icons',
'my-other-icons',
'my-yet-other-icons',
],
})
查看 Vue 3 + Vite 示例。
使用自定义外部集合包
从版本 v0.18.3
开始,你可以使用其他包来加载其他作者的图标。
警告:外部包必须包含 icons.json
文件,其中包含 IconifyJSON
格式的 icons
数据,可以使用 Iconify Tools 导出。查看 将图标集导出为 JSON 包 了解更多详情。
例如,你可以使用 an-awesome-collection
或 @my-awesome-collections/some-collection
来加载你的自定义或第三方图标:
// 加载器辅助函数
import { ExternalPackageIconLoader } from 'unplugin-icons/loaders'
Icons({ customCollections: ExternalPackageIconLoader('my-awesome-collection') })
当与解析器一起使用进行自动导入时,记住你需要告诉它你的自定义集合名称:
IconResolver({
customCollections: [
'my-awesome-collection',
],
})
你还可以将它与 FileSystemIconLoader
或其他自定义图标加载器结合使用:
// 加载器辅助函数
import { ExternalPackageIconLoader, FileSystemIconLoader } from 'unplugin-icons/loaders'
Icons({
customCollections: {
...ExternalPackageIconLoader('an-awesome-collection'),
...ExternalPackageIconLoader('@my-awesome-collections/some-collection'),
...ExternalPackageIconLoader('@my-awesome-collections/some-other-collection'),
'my-yet-other-icons': FileSystemIconLoader(
'./assets/icons',
svg => svg.replace(/^<svg /, '<svg fill="currentColor" '),
),
},
})
查看 Vue 3 + Vite 示例。
图标自定义器
从 v0.13
开始,你还可以使用 iconCustomizer
配置选项或在导入时使用查询参数来自定义每个图标。
query
参数的优先级高于 iconCustomizer
,而 iconCustomizer
的优先级高于 configuration
。
iconCustomizer
和 query
参数将应用于任何集合,即 custom
加载器、customCollections
中的 inlined
或来自 @iconify
的每个图标。
例如,你可以配置 iconCustomizer
来更改集合中的所有图标或集合中的单个图标:
import { promises as fs } from 'node:fs'
// 加载器辅助函数
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
Icons({
customCollections: {
// 键作为集合名称
'my-icons': {
account: '<svg><!-- ... --></svg>',
// 懒加载你的自定义图标
settings: () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),
/* ... */
},
'my-other-icons': async (iconName) => {
// 你的自定义加载器。可以做任何你想做的事。
// 例如,从远程服务器获取:
return await fetch(`https://example.com/icons/${iconName}.svg`).then(res => res.text())
},
// 一个从文件系统加载图标的辅助函数
// `./assets/icons` 下带 `.svg` 扩展名的文件将按其文件名加载
// 你还可以提供一个转换回调函数来改变每个图标(可选)
'my-yet-other-icons': FileSystemIconLoader(
'./assets/icons',
svg => svg.replace(/^<svg /, '<svg fill="currentColor" '),
),
},
iconCustomizer(collection, icon, props) {
// 自定义此集合中的所有图标
if (collection === 'my-other-icons') {
props.width = '4em'
props.height = '4em'
}
// 自定义此集合中的这个图标
if (collection === 'my-icons' && icon === 'account') {
props.width = '6em'
props.height = '6em'
}
// 自定义此集合中的这个 @iconify 图标
if (collection === 'mdi' && icon === 'account') {
props.width = '2em'
props.height = '2em'
}
},
})
或者你可以使用 query
参数应用于单个图标:
<script setup lang='ts'>
import MdiAlarmOff from 'virtual:icons/mdi/alarm-off?width=4em&height=4em'
import MdiAlarmOff2 from 'virtual:icons/mdi/alarm-off?width=1em&height=1em'
</script>
<template>
<!-- width=4em 和 height=4em -->
<mdi-alarm-off />
<!-- width=4em 和 height=4em -->
<MdiAlarmOff />
<!-- width=1em 和 height=1em -->
<MdiAlarmOff2 />
</template>
查看 vite-vue3
示例项目中的 src/App.vue
组件和 vite.config.ts
配置。
全局自定义图标转换
从版本 0.14.2
开始,在加载自定义图标时,你可以对它们进行转换,例如添加带有 currentColor
的 fill
属性:
Icons({
customCollections: {
// 键作为集合名称
'my-icons': {
account: '<svg><!-- ... --></svg>',
/* ... */
},
},
transform(svg, collection, icon) {
// 对此集合中的这个图标应用 fill
if (collection === 'my-icons' && icon === 'account')
return svg.replace(/^<svg /, '<svg fill="currentColor" ')
return svg
},
})
高级自定义图标集清理
当将此插件与你的自定义图标一起使用时,考虑使用类似于 Iconify 对任何图标集所做的清理过程。你需要的所有工具都可以在 Iconify Tools 中找到。
你可以查看这个仓库,在 SvelteKit
项目中使用 unplugin-icons
:https://github.com/iconify/tools/tree/main/%40iconify-demo/unplugin-svelte。
从 Iconify 的 清理图标 文章中了解更多详情。
从 vite-plugin-icons
迁移
package.json
{
"devDependencies": {
- "vite-plugin-icons": "*",
+ "unplugin-icons": "^0.7.0",
}
}
vite.config.json
import Components from 'unplugin-vue-components/vite'
- import Icons, { ViteIconsResolver } from 'vite-plugin-icons'
+ import Icons from 'unplugin-icons/vite'
+ import IconsResolver from 'unplugin-icons/resolver'
export default {
plugins: [
Vue(),
Components({
resolvers: [
IconsResolver()
],
}),
Icons(),
],
}
*
- 导入用法
- import IconComponent from 'virtual:vite-icons/collection/name'
+ import IconComponent from '~icons/collection/name'
如果你更喜欢,在 Vite 中仍可以使用
virtual:icons
前缀,但在 Webpack 中尚不支持,我们在文档中将其统一作为一种解决方案。
选项
你可以为所有图标设置默认样式。 以下配置显示了每个选项的默认值:
Icons({
scale: 1.2, // 图标相对于 1em 的缩放比例
defaultStyle: '', // 应用于图标的样式
defaultClass: '', // 应用于图标的类名
compiler: null, // 'vue2', 'vue3', 'jsx'
jsx: 'react', // 'react' 或 'preact'
})
自动导入
Vue 2 & 3
与 unplugin-vue-components
一起使用
例如在 Vite 中:
// vite.config.js
import Vue from '@vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'
export default {
plugins: [
Vue(),
Components({
resolvers: [
IconsResolver(),
],
}),
Icons(),
],
}
然后你可以随意使用任何图标,无需显式导入。只有使用到的图标会被打包。
<template>
<i-carbon-accessibility/>
<i-mdi-account-box style="font-size: 2em; color: red"/>
</template>
React & Solid
与 unplugin-auto-import
一起使用
例如在 Vite 中:
// vite.config.js
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import AutoImport from 'unplugin-auto-import/vite'
export default {
plugins: [
/* ... */
AutoImport({
resolvers: [
IconsResolver({
prefix: 'Icon',
extension: 'jsx',
}),
],
}),
Icons({
compiler: 'jsx', // 或 'solid'
}),
],
}
然后你可以使用带有 Icon
前缀的任何图标,无需显式导入。类型声明将会动态生成。
export function Component() {
return (
<div>
<IconCarbonApps />
<IconMdiAccountBox style="font-size: 2em; color: red" />
</div>
)
}
命名转换
使用组件解析器时,你必须遵循图标的命名转换规则,以便正确推断。
{prefix}-{collection}-{icon}
collection
字段遵循 Iconify 的集合 ID。
默认情况下,前缀设置为 i
,你可以通过配置自定义
IconsResolver({
prefix: 'icon', // <--
})
<template>
<icon-mdi-account />
</template>
也支持无前缀模式
IconsResolver({
prefix: false, // <--
// 这是可选的,默认启用 Iconify 支持的所有集合
enabledCollections: ['mdi'],
})
<template>
<mdi-account />
</template>
集合别名
使用组件解析器时,你必须使用可能很长或冗余的集合名称:例如,
使用 icon-park
集合时,你需要这样使用 <icon-icon-park-abnormal />
。
你可以为 IconResolver
插件中的任何集合添加别名:
IconsResolver({
alias: {
park: 'icon-park',
fas: 'fa-solid',
// ...
}
})
你可以使用别名或集合名称,插件将解析两者。
继续上面的例子,使用前面的 alias
条目配置插件后,你现在可以使用
<icon-park-abnormal />
或 <icon-icon-park-abnormal />
。
赞助商
本项目是我的赞助计划的一部分
许可证
MIT 许可证 © 2020-现在 Anthony Fu