进阶 unplugin.unjs.io 2026-10-08 10:00:35 · 6 阅读

第2章 unplugin-icons 第2章:通用化按需加载图标指南

4,937160unplugin-icons 通用化按需访问数千个图标组件。

特性

🌏 通用 🤹 支持任意图标集——约 150 个流行图标集,包含超过 200,000 个图标、Logo、表情符号等,由 Iconify 提供支持。

📦 主流构建工具——Vite、Webpack、Rollup、Nuxt、Rspack 等,由 unplugin 提供支持。

🚀 主流框架——Vanilla、Web Components、React、Vue 3、Vue Vapor、Solid、Svelte 等。欢迎参与贡献。

🍱 以上任意组合均可!

☁️ 按需加载——仅打包你实际使用的图标,同时保留所有配置选项。

🖨 支持 SSR / SSG——图标随页面一起发布,不再出现 FOUC(闪烁)。

🌈 可定制样式——像使用 CSS 类一样修改尺寸、颜色,甚至添加动画。

📥 自定义图标——轻松加载自定义图标,实现通用集成。

📲 自动导入——直接在模板中将图标作为组件使用。

🦾 支持 TypeScript。

🔍 浏览图标


💡 背后故事:与图标同行——Anthony 的博客文章

vite-plugin-icons 已更名为 unplugin-icons,请参阅迁移指南。从 v24.0.0 起,unplugin-icons 要求 Node 20 或更高版本:unplugin v3.0.0 要求 Node 20 或更高版本。

快速开始

基本用法

按照约定 ~icons/{collection}/{icon} 导入图标并将其作为组件使用。同时也支持自动导入。

React 示例:

import IconAccessibility from '~icons/carbon/accessibility'
import IconAccountBox from '~icons/mdi/account-box'

function App() {
  return (
    
) }
) }Vue 示例:vue 安装 ​注意:本包仅支持 ESM。请确保你的项目使用 ES 模块(package.json 中设置 "type": "module",或使用 .mjs 文件扩展名)。第 1 步:安装插件 ​bashnpm i -D unplugin-icons第 2 步:安装图标数据 ​我们使用 Iconify 作为图标数据源(支持 100+ 图标集)。提示✨ VS Code 用户:安装 Iconify IntelliSense 扩展,可获得内嵌预览、自动补全和悬停提示。方案 A:安装完整集合(推荐,更灵活)bashnpm i -D @iconify/json这会安装所有图标集(约 120MB)。生产构建时只会打包你实际用到的图标。方案 B:只安装需要的图标集bashnpm i -D @iconify-json/mdi @iconify-json/carbon方案 C:自动安装(实验性)让 unplugin-icons 在你导入图标集时自动安装:tsIcons({ autoInstall: true, // 自动检测 npm/yarn/pnpm })示例 ​前往 playgrounds 页面,在 StackBlitz 上在线试用示例。可用示例:Vite + Vue 3Vite + ReactNext.jsNuxt 4SvelteKitAstro等等……配置 ​本节介绍如何在不同的构建工具和框架中配置 unplugin-icons。构建工具 ​Vitets// vite.config.ts import Icons from 'unplugin-icons/vite' export default defineConfig({ plugins: [ Icons({ /* options */ }), ], })Rollupts// rollup.config.js import Icons from 'unplugin-icons/rollup' export default { plugins: [ Icons({ /* options */ }), ], }Webpackts// webpack.config.mjs import Icons from 'unplugin-icons/webpack' export default { /* ... */ plugins: [ Icons({ /* options */ }), ], }NuxtNuxt 2 和 Nuxt Bridgets// nuxt.config.ts export default { buildModules: [ ['unplugin-icons/nuxt', { /* options */ }], ], }Nuxt 3/4ts// nuxt.config.ts export default defineNuxtConfig({ modules: [ ['unplugin-icons/nuxt', { /* options */ }] ], })也可以配合 unplugin-vue-components resolver 使用:tsimport IconsResolver from 'unplugin-icons/resolver' import ViteComponents from 'unplugin-vue-components/vite' // nuxt.config.ts export default defineNuxtConfig({ modules: [ 'unplugin-icons/nuxt', ], vite: { plugins: [ ViteComponents({ resolvers: [ IconsResolver({/* options */}), ], }), ], }, })完整示例项目见 Nuxt example。Rspacktsimport Icons from 'unplugin-icons/rspack' // rspack.config.mjs export default defineConfig({ plugins: [ // ... Icons({/* options */}), ] })Vue CLI注意:本包仅支持 ESM。你需要使用 ES 模块语法的 vue.config.mjs(需要 @vue/cli-service ^5.0.8)。ts// vue.config.mjs import Icons from 'unplugin-icons/webpack' export default { configureWebpack: { plugins: [ Icons({ /* options */ }), ], }, }SvelteKit添加到你的 vite.config.ts:tsimport { sveltekit } from '@sveltejs/kit/vite' import Icons from 'unplugin-icons/vite' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ sveltekit(), Icons({ compiler: 'svelte', }) ] })如果遇到模块导入错误,请参考下方 Frameworks -> Svelte 一节的说明。完整示例项目见 SvelteKit example。Svelte + ViteSvelte 支持需要 @sveltejs/vite-plugin-svelte 插件:shellnpm i -D @sveltejs/vite-plugin-svelte添加到你的 vite.config.ts:tsimport { svelte } from '@sveltejs/vite-plugin-svelte' import Icons from 'unplugin-icons/vite' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ svelte(), Icons({ compiler: 'svelte', }), ], })如果遇到模块导入错误,请参考下方 Frameworks -> Svelte 一节的说明。完整示例项目见 Svelte + Vite example。Next.js注意:本包仅支持 ESM。你需要使用 ES 模块语法的 next.config.mjs。添加到你的 next.config.mjs:ts// 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 } }如果遇到模块导入错误,请参考下方 Frameworks -> React 一节的说明。⚠️ 注意:导入图标时必须在导入路径中显式加上 .jsx 扩展名,Next.js 才知道如何加载它,例如:tsimport IconArrowRight from '~icons/dashicons/arrow-right.jsx'; // ^-- 写上 `.jsx` 以避免 // https://github.com/antfu/unplugin-icons/issues/103 // ...后面的代码 完整示例项目见 Next.js example。esbuildts// esbuild.config.js import { build } from 'esbuild' import Icons from 'unplugin-icons/esbuild' build({ /* ... */ plugins: [ Icons({ /* options */ }), ], })Astrots// 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 example。Astro + Vue需要安装 @astrojs/vue。tsimport Vue from '@astrojs/vue' // astro.config.mjs import { defineConfig } from 'astro/config' import Icons from 'unplugin-icons/vite' // https://astro.build/config export default defineConfig({ integrations: [ Vue(), ], vite: { plugins: [ Icons({ compiler: 'vue3', }), ], }, })完整示例项目见 Astro + Vue example。框架 ​根据你的框架配置 compiler 选项。某些框架可能需要额外的 peer dependencies。Vue 3配置:tsIcons({ compiler: 'vue3' })Peer Dependency:注意:Vue 3.2.13+ 的 vue 主包已包含 @vue/compiler-sfc,无需额外安装。如果你使用的是旧版本:bashnpm i -D @vue/compiler-sfcTypeScript 支持:添加到 tsconfig.json:jsonc{ "compilerOptions": { "types": [ "unplugin-icons/types/vue" ] } }完整配置见 Vue 3 example。Vue Vapor输出 Vapor 模式组件而非虚拟 DOM 组件。用 createVaporApp 挂载且未启用 VDOM 互操作插件的应用,渲染虚拟 DOM 图标时会静默失败——不报错、不警告——所以 Vapor 应用需要使用此 compiler 而不是 vue3。配置:tsIcons({ compiler: 'vue-vapor' })Peer Dependency:需要 Vue 3.6+:bashnpm i -D @vue/compiler-vaporTypeScript 支持:添加到 tsconfig.json:jsonc{ "compilerOptions": { "types": [ "unplugin-icons/types/vue" ] } }React配置:tsIcons({ compiler: 'jsx', jsx: 'react' })Peer Dependencies:bashnpm i -D @svgr/core @svgr/plugin-jsxTypeScript 支持:添加到 tsconfig.json:jsonc{ "compilerOptions": { "types": [ "unplugin-icons/types/react" ] } }完整配置见 React example。Preact配置:tsIcons({ compiler: 'jsx', jsx: 'preact' })Peer Dependencies:bashnpm i -D @svgr/core @svgr/plugin-jsxTypeScript 支持:添加到 tsconfig.json:jsonc{ "compilerOptions": { "types": [ "unplugin-icons/types/preact" ] } }完整配置见 Preact example。Solid配置:tsIcons({ compiler: 'solid' })TypeScript 支持:添加到 tsconfig.json:jsonc{ "compilerOptions": { "types": [ "unplugin-icons/types/solid" ] } }完整配置见 Solid example。Svelte配置:tsIcons({ compiler: 'svelte' })TypeScript 支持:SvelteKit 项目,添加到 src/app.d.ts:tsimport 'unplugin-icons/types/svelte'Svelte + Vite 项目,添加到 src/vite-env.d.ts:ts/// /// /// Svelte 4 使用:ts/// Svelte 3 使用:ts/// 完整配置见 Svelte example。Astro配置:tsIcons({ compiler: 'astro' })TypeScript 支持:添加到 tsconfig.json:jsonc{ "compilerOptions": { "types": [ "unplugin-icons/types/astro" ] } }完整配置见 Astro example。Astro + Vue配置:tsIcons({ compiler: 'vue3' })要求:需要安装 @astrojs/vue。TypeScript 支持:添加到 tsconfig.json:jsonc{ "compilerOptions": { "types": [ "unplugin-icons/types/vue" ] } }完整配置见 Astro + Vue example。Qwik方案 1:原生 Qwik Compiler(推荐)配置:tsIcons({ compiler: 'qwik' })Peer Dependency:bashnpm i -D @svgx/core方案 2:JSX Compiler配置:tsIcons({ compiler: 'jsx', jsx: 'qwik' })Peer Dependencies:bashnpm i -D @svgr/core @svgr/plugin-jsxTypeScript 支持:添加到 tsconfig.json:jsonc{ "compilerOptions": { "types": [ "unplugin-icons/types/qwik" ] } }完整配置见 Qwik example。Ember配置:tsIcons({ compiler: 'ember' })构建工具支持:Ember 可以使用 Webpack 或 Vite。Vite 应用,添加到 vite.config.mjs:tsimport { ember, extensions } from '@embroider/vite' import { babel } from '@rollup/plugin-babel' import Icons from 'unplugin-icons/vite' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ ember(), Icons({ compiler: 'ember', }), babel({ babelHelpers: 'runtime', extensions, }), ], })TypeScript 支持:添加到 tsconfig.json:jsonc{ "compilerOptions": { "types": [ "unplugin-icons/types/ember" ] } }Ember + Webpack假设你的应用是通过 --embroider 生成的,或已按照旧版 embroider readme 的说明手动迁移到 embroider。将图标插件添加到 ember-cli-build.js 的 webpack plugins 数组:tsimport { compatBuild } from '@embroider/compat' import Icons from 'unplugin-icons/webpack' return compatBuild(app, Webpack, { packagerOptions: { webpackConfig: { plugins: [ Icons({ compiler: 'ember', }), ], }, }, // ...其他选项完整示例项目见 Ember (with Webpack) 或 Ember vite example。
原始 SVG 导入​该功能自 v0.13.2+ 版本起可用。在导入路径后添加 ?raw 即可将图标作为原始 SVG 字符串导入。此方法适用于在 HTML 模板中直接嵌入 SVG。示例 (Vue 3):vue 自定义图标 加载并复用你自己创建的图标,使用方式与其他通用 API 保持一致。 ts import { promises as fs } from 'node:fs' // 加载器辅助工具 import { FileSystemIconLoader } from 'unplugin-icons/loaders' Icons({ customCollections: { // 键名作为集合名称 'my-icons': { account: '', // 惰性加载自定义图标 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.replace(/^ svg.replace(/^ iconCustomizer > 默认配置 适用于所有图标来源:自定义加载器、内联集合以及 Iconify 集合。 例如,你可以配置 iconCustomizer 来更改集合中所有图标或特定图标的属性: ts import { promises as fs } from 'node:fs' // 加载器辅助工具 import { FileSystemIconLoader } from 'unplugin-icons/loaders' Icons({ customCollections: { // 键名作为集合名称 'my-icons': { account: '', // 惰性加载自定义图标 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(/^ import MdiAlarmOff from 'virtual:icons/mdi/alarm-off?width=4em&height=4em' import MdiAlarmOff2 from 'virtual:icons/mdi/alarm-off?width=1em&height=1em' 完整实现请参阅 Vue 3 示例。 全局图标转换 在加载过程中为所有自定义图标应用转换。常用于添加默认属性,如 fill="currentColor"。 ts Icons({ customCollections: { // 键名作为集合名称 'my-icons': { account: '', /* ... */ }, }, transform(svg, collection, icon) { // 为该集合中的此图标应用 fill 属性 if (collection === 'my-icons' && icon === 'account') return svg.replace(/^ {}, // 参见 [图标自定义](https://github.com/unplugin/unplugin-icons/tree/main/#icon-customization) transform: undefined, // 参见 [全局图标转换](https://github.com/unplugin/unplugin-icons/tree/main/#global-icon-transformation) autoInstall: false, // 导入时自动安装图标集 }) 自动导入 Vue 3 配合 unplugin-vue-components 使用 例如在 Vite 中: ts // vite.config.ts import Vue from '@vitejs/plugin-vue' import IconsResolver from 'unplugin-icons/resolver' import Icons from 'unplugin-icons/vite' import Components from 'unplugin-vue-components/vite' export default { plugins: [ Vue(), Components({ resolvers: [ IconsResolver(), ], }), Icons(), ], } 这样你就可以在不显式导入的情况下随意使用任何图标。只有实际使用的图标会被打包。 html React & Solid 配合 unplugin-auto-import 使用 例如在 Vite 中: ts // vite.config.ts import AutoImport from 'unplugin-auto-import/vite' import IconsResolver from 'unplugin-icons/resolver' import Icons from 'unplugin-icons/vite' export default { plugins: [ AutoImport({ resolvers: [ IconsResolver({ prefix: 'Icon', extension: 'jsx', }), ], }), Icons({ compiler: 'jsx', // 或 'solid' }), ], } 这样你就可以在不显式导入的情况下,使用前缀 Icon 随意使用任何图标。类型声明将即时生成。 jsx export function Component() { return (
) }组件命名 ​图标会按照以下命名规则自动导入:{prefix}-{collection}-{icon}prefix:组件名前缀(默认:i)collection:Iconify 集合 ID(如 mdi、carbon、fa-solid)icon:图标名称(kebab-case 格式)自定义前缀:tsIconsResolver({ prefix: 'icon', // 用 'icon' 代替 'i' })vue不用前缀:tsIconsResolver({ prefix: false, enabledCollections: ['mdi'], // 可选:限定只用特定集合 })vue集合别名 ​可以为较长的集合名称设置更短的别名:tsIconsResolver({ alias: { park: 'icon-park', // 用 代替 fas: 'fa-solid', // 用 代替 } })别名和完整集合名都可以使用:vue赞助 ​本项目是我的赞助计划的一部分许可证 ​MIT License © 2020-PRESENT Anthony Fu

评论 (0)