Vue编译为Web Component后Font Awesome字体图标无法渲染如何解决
我有一个Vue组件,正使用如下构建命令将其编译为Web Component:
npm run build -- --target wc --name projName src\components\server-config.vue
但我的Vue文件中缺少部分配置,导致Web Component无法渲染Font Awesome图标。执行npm run serve时的正常效果如下:
编译为Web Component后在demo.html中打开的异常效果如下:
目前发现的问题如下:
- 字体样式存在差异
- 密码预览的眼睛按钮缺失
- 复选框框体缺失(鼠标悬浮时仍可触发光晕效果)
- Vuetify外的独立测试眼形图标缺失
请问我该如何正确将字体引入到组件中?以下是我当前的Vue文件代码:
<template> <div style="text-align: center; font-family: sans-serif"> <v-text-field label="Password" class="mx-4" v-model="password" :type="showPass ? 'text' : 'password'" @click:append="showPass = !showPass" :append-icon="showPass ? 'far fa-eye' : 'far fa-eye-slash'"></v-text-field> <v-checkbox class="mx-4" v-model="useIntegratedAuthentication" label="Use Integrated Authentication" ></v-checkbox> <div> <i class="far fa-eye"></i> <span>My eye here</span> </div> </div> </template> <style scoped> @import '../../node_modules/vuetify/dist/vuetify.min.css'; @import 'https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900'; @import 'https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css'; </style> <script src="https://kit.fontawesome.com/XXXXXXXXX.js" crossorigin="anonymous"></script> <script lang="ts"> import { VTextField, VCheckbox } from 'vuetify/lib'; import vuetify from '@/plugins/vuetify'; import Vue from 'vue'; export default Vue.extend({ vuetify, components: { VTextField, VCheckbox }, data() { return { showPass: false, password: '', useIntegratedAuthentication: false }; } }) </script>
解决方案
问题核心是Web Component的Shadow DOM隔离特性,外部引入的样式、字体资源默认不会穿透到Shadow DOM内部,你当前的引入方式存在两处错误:一是Font Awesome的CDN脚本放在Vue SFC的script标签外部,编译时不会被打包也不会作用到Shadow DOM内;二是带scoped属性的style块引入的外部资源,打包为Web Component时路径会失效,第三方图标字体的声明也没有被正确注入到Shadow DOM中。
第一步:配置Vuetify的Font Awesome图标源
修改你的vuetify插件(@/plugins/vuetify.ts),指定使用Font Awesome作为图标源,配置示例如下:
import Vue from 'vue' import Vuetify from 'vuetify/lib' import { library } from '@fortawesome/fontawesome-svg-core' import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import { faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons' // 注册用到的Font Awesome图标 library.add(faEye, faEyeSlash) Vue.component('font-awesome-icon', FontAwesomeIcon) Vue.use(Vuetify) export default new Vuetify({ icons: { iconfont: 'faSvg', // 明确指定使用Font Awesome SVG格式 }, })
如果还没有安装相关依赖,先执行安装命令:
npm install @fortawesome/fontawesome-svg-core @fortawesome/vue-fontawesome @fortawesome/free-regular-svg-icons @fortawesome/free-solid-svg-icons
第二步:清理无效的外部引入
删除Vue文件里单独写的<script src="https://kit.fontawesome.com/XXXXXXXXX.js" crossorigin="anonymous"></script>这段代码,同时去掉style块的scoped属性,调整样式引入:
<style> @import 'vuetify/dist/vuetify.min.css'; @import 'https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900'; </style>
第三步:调整打包配置
可以在原有打包命令基础上添加--inline-css参数,确保所有样式被内联到JS文件中,不会分离为独立CSS文件:
npm run build -- --target wc --name projName --inline-css src/components/server-config.vue
第四步:验证效果
打包完成后在demo.html中引入生成的projName.js即可,所有图标、字体样式都会被内置到Web Component的Shadow DOM中,不需要在外部页面额外引入Vuetify或者Font Awesome资源。
内容的提问来源于stack exchange,提问作者Jon Dosmann

