Vue3+Vite项目中FontAwesome图标懒加载开发环境失效问题
Vue3+Vite中FontAwesome按需加载的开发环境异常问题
在Vue3+Vite项目中使用官方FontAwesome Vue3包时,静态预加载图标(通过library.add)可正常运行,但通过import.meta.glob实现点击按需加载时,开发环境出现异常,生产构建后却能正常工作。
静态加载正常代码
<script setup> import { ref } from "vue"; import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { definition } from "@fortawesome/free-solid-svg-icons/faTruck"; library.add(definition); const icon = ref(""); const showIcon = () => { icon.value = `fa-solid fa-truck`; }; </script> <template> <button @click="showIcon">Show Truck Icon</button> <div v-if="icon"> <font-awesome-icon :icon="icon" /> </div> </template>
按需加载异常代码
<script setup> import { ref } from "vue"; import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; const modules = import.meta.glob( "../node_modules/@fortawesome/free-solid-svg-icons/faTruck.js", { eager: false, import: "definition" } ); const icon = ref(""); const showIcon = () => { Object.values(modules)[0]().then((elem) => { library.add(elem); icon.value = `fa-solid fa-truck`; }); }; </script> <template> <button @click="showIcon">Show Truck Icon</button> <div v-if="icon"> <font-awesome-icon :icon="icon" /> </div> </template>
开发环境异常现象
- 浏览器发起请求到
http://localhost:5173/node_modules/@fortawesome/free-solid-svg-icons/faTruck.js - 控制台抛出错误:
Uncaught (in promise) ReferenceError: exports is not defined
复现步骤
npm create vue@3 # 接受所有默认配置 cd vue-project npm i @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/vue-fontawesome # 将src/App.vue替换为上述按需加载代码 # 启动开发环境 npm run dev # 生产构建验证 npm run build npx http-server dist
解决方案
1. 配置Vite转译FontAwesome图标模块
问题根源是开发环境中Vite未转译@fortawesome/free-solid-svg-icons模块,导致CommonJS格式的代码直接在浏览器中运行报错。修改vite.config.js,让Vite优化该依赖:
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], optimizeDeps: { include: ['@fortawesome/free-solid-svg-icons'] } })
同时修正import.meta.glob的路径,避免直接引用node_modules,改用包路径写法(支持批量匹配):
const modules = import.meta.glob( "@fortawesome/free-solid-svg-icons/fa*.js", { eager: false, import: "definition" } );
2. 直接使用动态import(单图标场景)
如果不需要批量匹配图标,直接用动态import替代import.meta.glob,更简洁且无需额外配置:
<script setup> import { ref } from "vue"; import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; const icon = ref(""); const showIcon = () => { import("@fortawesome/free-solid-svg-icons/faTruck") .then(({ definition }) => { library.add(definition); icon.value = `fa-solid fa-truck`; }); }; </script> <template> <button @click="showIcon">Show Truck Icon</button> <div v-if="icon"> <font-awesome-icon :icon="icon" /> </div> </template>
3. 利用FontAwesome的动态注册API
可以结合fontawesome-svg-core的icon()方法,在动态加载后直接注册,无需通过library.add,不过同样需要确保模块被Vite转译:
<script setup> import { ref } from "vue"; import { icon } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; const iconData = ref(null); const showIcon = () => { import("@fortawesome/free-solid-svg-icons/faTruck") .then(({ definition }) => { iconData.value = icon(definition); }); }; </script> <template> <button @click="showIcon">Show Truck Icon</button> <div v-if="iconData"> <font-awesome-icon :icon="iconData" /> </div> </template>
内容的提问来源于stack exchange,提问作者digEmAll
相关产品推荐
相关产品推荐

