- 前端
- UI组件
【免费下载链接】pdfx
A React PDF component library with pre-built, themeable components and a CLI for seamless PDF document creation.
PDFx 是一个基于 React 的 PDF 组件库,它的字体配置决定了生成文档的排版效果。本文带你掌握 PDFx 自定义字体注册、中文字体支持与离线环境字体避坑的核心方法,帮助你在浏览器端、Node.js 服务端和无网络的受限环境中都能稳定渲染出美观的 PDF。
一、为什么 PDFx 需要单独配置字体?
PDF 与网页不同:浏览器会自动加载系统字体,但PDF 文件必须内嵌字体,否则无法保证在任何设备上显示一致。PDFx 底层使用@react-pdf/renderer渲染,因此字体分两类:
| 字体类型 | 是否需要注册 | 说明 |
|---|---|---|
PDF 标准 14 字体(如Helvetica、Times-Roman、Courier) | ❌ 开箱即用 | 内嵌于所有 PDF 阅读器,但不支持中文 |
| 自定义字体(Inter、Noto Sans SC 等) | ✅ 必须Font.register() | 支持任意语言,字体文件会内嵌进 PDF |
💡 关键认知:PDFx 的所有组件(Heading、Text、Table 等)都不硬编码字体,而是读取主题里的字体令牌。你只需在两个地方配置好字体,整份文档自动生效:
- 注册字体:用
Font.register()告诉渲染引擎"字体文件在哪" - 主题令牌:在主题文件里通过
fontFamily指定"哪个位置用哪个字体"
字体令牌的类型定义见 theme.ts,每个主题文件(如 corporate.ts、elegant.ts)都按这套结构声明正文与标题字体。
二、自定义字体注册:三步搞定
第 1 步:调用 Font.register()
字体注册是一个副作用操作——在渲染任何 PDF 之前导入一次即可,react-pdf 会在首次下载后自动缓存字体:
import { Font } from '@react-pdf/renderer'; Font.register({ family: 'Inter', fonts: [ { src: 'https://cdn.jsdelivr.net/npm/@fontsource/inter@4/files/inter-latin-400-normal.woff', fontWeight: 400 }, { src: 'https://cdn.jsdelivr.net/npm/@fontsource/inter@4/files/inter-latin-700-normal.woff', fontWeight: 700 }, ], });fonts数组允许为同一字体家族注册多个字重(400/500/600/700),并可通过fontStyle: 'italic'注册斜体。官网 Theme Builder 内置的 10 款字体(Inter、Roboto、Lato、Merriweather、JetBrains Mono 等)完整注册示例见 pdf-fonts.ts。
第 2 步:浏览器端用 URL,服务端用文件路径
这是新手最常踩的第一个坑:两端字体来源不同。
- 浏览器端:
src填字体文件的 URL - Node.js 服务端:
src填文件系统的绝对路径,因为服务端没有浏览器网络 API
官方文档中的示例见 server-side.tsx:
// 服务端:从本地文件系统加载 Font.register({ family: 'Inter', src: path.resolve('./public/fonts/Inter-Regular.ttf'), }); // 浏览器端:从 URL 加载 Font.register({ family: 'Inter', src: 'https://fonts.gstatic.com/s/inter/v13/Inter-Regular.ttf', });第 3 步:在主题中引用字体家族名
注册之后,把family的名字写进主题的fontFamily令牌即可,例如 docs.constant.ts 中的品牌主题:
typography: { heading: { fontFamily: 'Helvetica-Bold', fontWeight: 700, /* ... */ }, body: { fontFamily: 'Helvetica', fontSize: 11, lineHeight: 1.5 }, },⚠️ 名字必须与
Font.register()里的family完全一致,多一个空格都会导致字体回退为默认样式。
三、中文字体:PDF 渲染的"隐形杀手"
这是 PDFx 用户最常遇到的问题:中文全部显示为方块或缺字。
根本原因:PDF 标准 14 字体(Helvetica、Times-Roman 等)的字符集不包含 CJK(中日韩)字符。只要文档里出现中文,就必须注册一款中文字体。
正确的做法
- 选择一款开源中文字体,如Noto Sans SC(思源黑体)或Source Han Serif SC(思源宋体)
- 下载
.ttf或.otf文件(不要找 woff2,原因见下节) - 注册并引用:
import { Font } from '@react-pdf/renderer'; Font.register({ family: 'Noto Sans SC', src: './fonts/NotoSansSC-Regular.ttf', });- 在主题中将
body.fontFamily改为'Noto Sans SC'
避坑清单:
- ❌不要使用 WOFF2 格式的中文字体——
@react-pdf/renderer依赖的 fontkit 对 WOFF2(尤其含可变字体表的版本)解压支持有问题,这正是 pdf-fonts.ts 中明确注释、并坚持使用 WOFF 格式的原因 - ⚠️中文字体文件体积大(全字符集通常 10MB+),生成 PDF 时会被内嵌,显著增大文件。建议按实际用字做字体子集化(font subsetting),只保留用到的汉字
- ✅ 中英文混排文档:可分别注册西文字体与中文字体,正文用中文字体兜底,标题用西文品牌字体
- ✅ 字体文件放在项目内随代码一起部署(如
public/fonts/),避免运行时依赖外部下载
四、离线 / 内网环境:字体加载避坑
在无外网、内网隔离、生产环境锁网等场景下,通过 jsDelivr 等 CDN 加载字体的主题代码会直接失效。PDFx 官方在主题代码生成器中内置了明确的降级提示,见 theme-code-generator.ts:
For locked-down or offline production environments, self-host these fonts or switch to built-in fonts. (对于锁网或离线生产环境,请自托管字体或改用内置字体。)
两条官方推荐路线:
| 方案 | 适用场景 | 做法 |
|---|---|---|
| 自托管字体(推荐) | 需要品牌字体、中文等 | 将.ttf/.otf文件放进项目,服务端用绝对路径注册,浏览器端放到静态资源目录用相对 URL |
| 退回内置字体 | 纯英文文档 | 主题fontFamily改回Helvetica、Times-Roman等标准字体,零网络依赖 |
额外提醒:
- 字体注册是模块级副作用,确保注册模块在渲染前被导入(参考 ThemePreviewDocument.tsx 顶部的
import '../../lib/pdf-fonts'写法) - react-pdf 首次会下载字体文件,之后按 URL 缓存——离线环境首次生成仍需网络可达,或改用本地文件注册彻底规避
- 服务端渲染(
renderToBuffer/renderToStream)在纯 Node 环境运行,window、document等浏览器全局变量不可用,字体加载路径必须走文件系统
五、用 Theme Builder 零代码配置字体
如果你不想手写注册代码,可以用 PDFx 官方的Theme Builder可视化界面:
- 界面提供 3 类共 10 款开源自选字体(无衬线/衬线/等宽),按类别分组,字体目录定义见 pdf-fonts.ts
- 选择字体后,工具会自动生成对应的
Font.register()代码片段(generateGoogleFontRegistrationSnippet),连同主题代码一起导出 - 导出的主题代码会自动附上"离线环境请自托管字体"的注释提醒,闭环覆盖本文第四节
生成结果会写入项目中的src/lib/pdfx-theme.ts,组件运行期通过<PdfxThemeProvider>上下文读取,可在不打断构建的情况下运行时切换主题(含字体)。
六、常见问题速查(FAQ)
| 症状 | 原因 | 解决 |
|---|---|---|
| 中文显示为方块/缺字 | 使用标准 14 字体,不含 CJK 字符 | 注册 Noto Sans SC 等中文字体 |
| 字体没生效,仍是默认样式 | fontFamily与family名称不一致 | 核对拼写与大小写 |
| 粗体不生效、字重变细 | 只注册了 400 字重,主题却要求 700 | 在fonts数组中补充对应fontWeight |
| 浏览器正常、服务端报错 | 服务端用了 URL 或相对路径 | 服务端改用path.resolve()绝对路径 |
| WOFF2 字体加载后乱码/报错 | fontkit 对 WOFF2 可变字体表解压问题 | 换用 WOFF 或 TTF 格式 |
| 内网环境 PDF 生成卡死 | 运行时尝试访问 CDN 字体 | 自托管字体文件或改用内置字体 |
总结
PDFx 字体配置的核心就三件事:注册(Font.register指明字体文件位置)、引用(主题fontFamily令牌指向字体家族)、适配环境(浏览器用 URL、服务端用文件路径、离线环境自托管)。把这三步做对,配合官方 Theme Builder 的零代码调参,你就能在任意环境下稳定输出字体专业、多语言就绪的 PDF 文档。📄
- 前端
- UI组件
【免费下载链接】pdfx
A React PDF component library with pre-built, themeable components and a CLI for seamless PDF document creation.
相关推荐
GoFPDF字体配置指南:TrueType字体支持与自定义字体嵌入
GoFPDF字体配置指南:TrueType字体支持与自定义字体嵌入 想要在Go语言项目中生成专业PDF文档吗?GoFPDF提供了强大的字体配置功能,支持True
clip自定义字体配置:从系统字体到自定义字体的完全指南
clip自定义字体配置:从系统字体到自定义字体的完全指南 想要让你的命令行图表脱颖而出吗?clip 命令行图表工具的终极字体自定义功能能够彻底改变你的数据可视化
NW.js WebGL 3D应用开发:three.js集成实战
NW.js WebGL 3D应用开发:three.js集成实战 NW.js作为一款强大的桌面应用开发框架,让开发者能够使用Web技术构建跨平台应用。本文将带您探
示例工程桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考