Expo SDK45.0.4升级后FontAwesome字体未加载致图标不显示
Expo SDK45升级后@expo/vector-icons图标加载失败修复方案
升级至Expo SDK45.0.4版本后,应用全量图标无法加载,报错提示:fontFamily "FontAwesome" is not a system font and has not been loaded through Font.loadAsync。
问题根因
- 依赖版本不匹配:Expo SDK45 适配的
@expo/vector-icons版本为13.0.0,当前项目使用的^12.0.0版本和SDK45内置字体加载逻辑不兼容 - 第三方字体包冲突:项目引入的
@use-expo/font包会劫持SDK45内置的字体注册流程,导致图标字体无法正常挂载 - 预加载逻辑错误:现有异步加载字体的代码存在API引入缺失、组件用法错误问题,实际没有完成字体注册
修复步骤
第一步:对齐依赖版本
- 卸载冲突包与旧版本图标库
yarn remove @expo/vector-icons @use-expo/font
- 安装SDK45对应兼容版本的依赖
yarn add @expo/vector-icons@13.0.0 expo-font@~10.1.0
注意:SDK45已内置
expo-font完整能力,无需额外引入第三方字体加载包,旧包会直接导致图标字体注册失败。
第二步:修正字体预加载逻辑
原有加载代码存在三个问题:未正确引入expo-font的Font对象、AppLoading组件错误嵌套子组件(该组件为无UI占位组件,不支持children属性,嵌套会导致加载逻辑不执行)、未覆盖项目用到的全量图标字体。
替换App入口的加载逻辑为以下代码:
import React, { useState } from 'react'; import AppLoading from 'expo-app-loading'; import * as Font from 'expo-font'; import { FontAwesome, Ionicons } from '@expo/vector-icons'; // 项目用到的其他图标包可按相同格式引入 const cacheFonts = (fonts) => fonts.map((font) => Font.loadAsync(font)); export default function App() { const [fontLoaded, setFontLoaded] = useState(false); const loadAssets = async () => { // 此处注册项目中所有用到的图标字体 const fontAssets = cacheFonts([ FontAwesome.font, Ionicons.font // 用到其他图标库按相同格式追加即可 ]); await Promise.all(fontAssets); }; if (!fontLoaded) { return ( <AppLoading startAsync={loadAssets} onFinish={() => setFontLoaded(true)} onError={(err) => console.error('字体加载失败:', err)} /> ); } // 字体加载完成后返回原有App根组件,例如导航容器、UI主题Provider等 return <>{/* 原有根组件内容 */}</>; }
第三步:全量清缓存重启
依赖和代码修改完成后,执行以下命令彻底清除旧缓存,避免缓存干扰:
# 清除expo与metro打包缓存 expo r -c # 额外删除本地构建缓存目录 rm -rf .expo .webpack-cache node_modules/.cache
额外排查点
如果完成以上操作后问题仍存在,可检查两项配置:
- 所有图标字体的加载必须放在App最外层预加载阶段完成,禁止在业务组件渲染过程中动态注册字体
- 如果项目存在自定义
metro.config.js配置,确认ttf格式在资源扩展名assetExts列表中,没有被自定义规则覆盖
内容的提问来源于stack exchange,提问作者Giovanni Bianciardi
相关产品推荐
相关产品推荐

