在React Vite+TypeScript中@react-pdf/pdf自定义字体失效问题
解决React Vite项目中@react-pdf/renderer自定义TTF字体无法加载的问题
问题诊断
你遇到的核心问题有两个:
- Vite字体导入方式不匹配:直接导入TTF文件时,Vite默认返回资源URL,但
@react-pdf/renderer的Font.register需要字体文件的原始二进制数据(ArrayBuffer)才能正确解析。 - 字体注册规范错误:将每个字重的字体单独注册为独立家族,不符合react-pdf的字体管理逻辑,应该将同一家族的不同字重/样式归为一个字体家族,通过
weight和style区分。
解决方案
1. 调整字体导入方式(获取ArrayBuffer)
在导入字体文件时添加?arraybuffer后缀,让Vite返回字体的二进制数据而非URL:
import { Font, StyleSheet } from '@react-pdf/renderer'; // 导入时指定arraybuffer格式 import PrometoBold from '../../../../assets/fonts/Prometo-Bold.ttf?arraybuffer'; import PrometoMedium from '../../../../assets/fonts/Prometo-Medium.ttf?arraybuffer'; import PrometoRegular from '../../../../assets/fonts/Prometo-Regular.ttf?arraybuffer'; import PrometoLightItalic from '../../../../assets/fonts/Prometo-LightItalic.ttf?arraybuffer';
2. 正确注册字体家族
将同一款字体的不同字重/样式归为同一个家族,通过weight和style字段区分:
// 注册Prometo字体家族 Font.register({ family: 'Prometo', fonts: [ { src: PrometoRegular, weight: 'normal', style: 'normal' }, { src: PrometoMedium, weight: '500', style: 'normal' }, { src: PrometoBold, weight: 'bold', style: 'normal' }, { src: PrometoLightItalic, weight: '300', style: 'italic' } ] });
3. 样式中指定字体家族和字重
在StyleSheet中使用统一的字体家族名,并通过fontWeight指定对应字重:
const styles = StyleSheet.create({ title: { fontFamily: 'Prometo', // 使用注册的家族名 fontWeight: 'bold', // 匹配注册的bold字重 textAlign: 'center', color: '#001C43', fontSize: 24, marginBottom: 10 } });
4. 可选:配置Vite确保字体资源被正确处理
如果Vite对TTF文件的处理有异常,在vite.config.js中添加资源包含规则:
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], assetsInclude: ['**/*.ttf'] // 确保TTF文件被识别为资源 });
验证组件代码
调整后的PDF组件无需修改核心结构,确保字体注册代码在组件渲染前执行即可:
const PdfDocument = () => { return( <Document> <Page size="A4" wrap={true}> <Text style={styles.title}>This my title</Text> </Page> </Document> ); }; export default PdfDocument;
内容的提问来源于stack exchange,提问作者Gery
相关产品推荐
相关产品推荐

