💥 前端导出 PDF 全攻略:一文读懂 react-pdf 实战与性能优化

186 阅读4分钟

🧩 前端导出 PDF 全攻略:react-pdf 实战与性能优化指南(附完整示例)

💬 前言:当产品经理再次说“导出个 PDF 吧~”

👩‍💼 产品经理:能不能支持一下导出 PDF?就一个按钮,很简单的~
👨‍💻 前端:???
👩‍💼 产品经理:就和 Excel 一样嘛,一键下载那种。
👨‍💻 前端(内心 OS):Excel?PDF?一键?你怕不是想让我写打印机驱动 😭

听起来轻松的需求,做起来却是前端噩梦系列:

  • 一导出就样式错乱;
  • 中文字体全成方块;
  • 图表模糊得像 240p;
  • 文件一大就卡到浏览器假死。

于是我们开始疯狂搜索:

“react 导出 pdf 怎么实现”
“html2canvas 导出模糊怎么办”
“jsPDF 中文乱码解决方案”

最后发现,真正优雅的方案,其实藏在一个名字里:
🎯 @react-pdf/renderer —— 一个让你用 React 写 PDF 的神器。


一、前端导出 PDF 的几种主流方案

工具 / 库核心思路优点缺点
html2canvas + jsPDF把 DOM 截图再拼成 PDF快速上手,兼容性强模糊、样式丢失、性能差
react-pdf (@react-pdf/renderer)React 组件直接渲染为 PDF结构清晰,质量高,可控性强学习曲线略高
pdfmake / pdf-lib手动构建 PDF 元素灵活强大,版式精准开发成本高,不适合复杂布局
Puppeteer 服务端导出Headless Chrome 渲染 HTML精度高,接近打印效果依赖后端,部署复杂

👉 如果你是做 报表 / 图表 / 结算表 / 发票导出
推荐直接上 react-pdf,它是真正适合前端的方案。


二、react-pdf 是什么?

📘 官方地址: react-pdf.org/
📦 NPM 包: www.npmjs.com/package/@re…

@react-pdf/renderer 是一个将 React 组件直接渲染为 PDF 文档 的库。
它的核心理念:

「用 React 写 PDF,组件化地构建文档结构。」

核心优势:

  • 🔤 矢量级清晰排版,文本可选中、可复制。
  • 🧩 与 React 语法一致,支持组件与状态。
  • 🖨️ 支持 Node、浏览器、流式输出,灵活部署。

三、快速上手:Hello PDF 👋

安装依赖

npm install @react-pdf/renderer

创建一个简单示例

import { Page, Text, View, Document, StyleSheet, pdf } from '@react-pdf/renderer';

// 样式定义
const styles = StyleSheet.create({
  page: { padding: 20 },
  title: { fontSize: 20, fontWeight: 'bold', marginBottom: 10 },
  text: { fontSize: 12, lineHeight: 1.6 },
});

// PDF 文档组件
const MyDocument = () => (
  <Document>
    <Page style={styles.page}>
      <Text style={styles.title}>React PDF 导出示例</Text>
      <Text style={styles.text}>
        这是一个使用 @react-pdf/renderer 生成的 PDF 文档。
      </Text>
    </Page>
  </Document>
);

// 导出 PDF 的函数
const generatePdf = async () => {
  const blob = await pdf(<MyDocument />).toBlob();
  const url = URL.createObjectURL(blob);
  window.open(url);
};

点击按钮 → 即可直接预览 PDF!
没有截图模糊、没有排版乱。


四、复杂场景:图表、表格、报表导出

✅ 图表导出

react-pdf 不直接支持 <canvas> / <svg>
所以常见做法是:

  1. 用 ECharts / Chart.js 生成 base64 图;
  2. 再用 <Image src={base64} /> 插入 PDF。
const base64 = chartInstance.getDataURL();
<Image src={base64} />

✅ 表格导出

用 Flex 布局就能构建结构化表格:

<View style={{ flexDirection: 'row', borderBottom: '1px solid #ccc' }}>
  <Text style={{ flex: 1 }}>产品</Text>
  <Text style={{ flex: 1 }}>数量</Text>
  <Text style={{ flex: 1 }}>金额</Text>
</View>

大表格可以用 wrap 自动分页:

<Page wrap> ... </Page>

五、中文字体与排版(重点⚠️)

默认字体库不支持中文,需要手动注册字体:

import { Font } from '@react-pdf/renderer';
import fontSrc from './fonts/NotoSansSC-Regular.ttf';

Font.register({
  family: 'Noto Sans SC',
  src: fontSrc,
});

const styles = StyleSheet.create({
  text: { fontFamily: 'Noto Sans SC', fontSize: 12 },
});

✅ 推荐字体:

  • 思源黑体(Noto Sans SC)
  • 微软雅黑(Microsoft YaHei)

这样就能完美显示中文!


六、性能优化技巧

  1. 分页渲染
    大文档拆成多页异步渲染,避免阻塞。
  2. 延迟生成图表
    仅在导出时调用图表 getDataURL()
  3. 缓存静态模板
    对固定报表结构用预定义组件模板。
  4. 使用 Web Worker 导出
    避免主线程卡顿,保持导出体验流畅。

七、react-pdf vs html2canvas 对比总结

特性react-pdfhtml2canvas + jsPDF
清晰度✅ 矢量级❌ 模糊截图
文本可复制✅ 可选中❌ 不可复制
中文支持✅ 可注册字体❌ 容易乱码
性能✅ 分页渲染⚠️ 受 DOM 影响大
适合复杂布局✅ 是❌ 否
推荐指数⭐⭐⭐⭐⭐⭐⭐

八、结语

“PDF 导出不是一个功能,而是一场排版与性能的平衡艺术。”

react-pdf 让前端 PDF 导出不再依赖截图,而是真正的文档构建。
无论是图表报告、月结账单、发票,还是统计分析,都能优雅搞定。

如果你的项目里有「导出 PDF」需求,
试试 @react-pdf/renderer ——
一次上手,终身不想回到 html2canvas。