如何在NextJS中使用@react-pdf/renderer生成PDF文件
Next.js 项目集成 @react-pdf/renderer 实现PDF生成落地指南
1. 安装依赖
执行以下命令安装核心包:
npm install @react-pdf/renderer # 或 yarn add @react-pdf/renderer # 或 pnpm add @react-pdf/renderer
2. Next.js 专属适配配置
如果你使用的是 Next.js 13+ App Router 版本,需要先在 next.config.js 中添加如下配置,解决服务端组件依赖兼容问题:
/** @type {import('next').NextConfig} */ const nextConfig = { experimental: { serverComponentsExternalPackages: ['@react-pdf/renderer'], } } module.exports = nextConfig
3. 编写PDF模板组件
新建 components/PdfTemplate.jsx 文件作为PDF内容模板,示例代码如下:
// 客户端使用时需要添加该标记 'use client' import { Document, Page, Text, View, StyleSheet } from '@react-pdf/renderer' // 定义PDF样式 const styles = StyleSheet.create({ page: { padding: 30, }, section: { margin: 10, padding: 10, }, title: { fontSize: 24, marginBottom: 20, } }) // 模板组件支持传入自定义数据 const PdfTemplate = ({ data }) => ( <Document> <Page size="A4" style={styles.page}> <View style={styles.section}> <Text style={styles.title}>PDF 生成测试</Text> <Text>用户名称:{data.userName}</Text> <Text>生成时间:{data.generateTime}</Text> </View> </Page> </Document> ) export default PdfTemplate
如果需要显示中文,需要提前注册中文字体,在模板文件顶部添加如下代码:
import { Font } from '@react-pdf/renderer' // 导入本地中文字体文件,需将字体文件放在public/fonts目录下 Font.register({ family: 'SourceHanSans', src: '/fonts/SourceHanSansCN-Normal.ttf' }) // 随后在Page的style中指定fontFamily为你注册的字体名称即可
4. 两种生成场景实现
场景1:客户端点击按钮直接下载PDF
适合PDF数据不敏感、内容较轻量的场景,直接在页面组件中使用 PDFDownloadLink 组件即可:
'use client' import { PDFDownloadLink } from '@react-pdf/renderer' import PdfTemplate from '@/components/PdfTemplate' export default function PdfDownloadPage() { // 自定义传入模板的业务数据 const pdfData = { userName: '测试用户', generateTime: new Date().toLocaleString() } return ( <div> <h1>下载PDF文件</h1> <PDFDownloadLink document={<PdfTemplate data={pdfData} />} fileName="测试文件.pdf" > {({ loading }) => loading ? '正在生成PDF...' : '点击下载PDF'} </PDFDownloadLink> </div> ) }
如果使用 Pages Router 或者遇到 document is not defined 报错,改用动态导入关闭SSR即可:
import dynamic from 'next/dynamic' const PDFDownloadLink = dynamic( () => import('@react-pdf/renderer').then(mod => mod.PDFDownloadLink), { ssr: false } )
场景2:服务端生成PDF返回
适合数据敏感、PDF内容复杂度高的场景,通过Next.js接口路由实现:
如果是 App Router,新建 app/api/generate-pdf/route.js 文件:
import { renderToBuffer } from '@react-pdf/renderer' import PdfTemplate from '@/components/PdfTemplate' import { NextResponse } from 'next/server' export async function GET() { // 服务端获取业务数据,比如从数据库查询 const pdfData = { userName: '服务端生成测试', generateTime: new Date().toLocaleString() } // 生成PDF buffer const buffer = await renderToBuffer(<PdfTemplate data={pdfData} />) // 返回PDF文件响应 return new NextResponse(buffer, { headers: { 'Content-Type': 'application/pdf', 'Content-Disposition': 'attachment; filename="服务端生成测试.pdf"' } }) }
前端直接请求该接口即可触发下载:
<a href="/api/generate-pdf" target="_blank" rel="noreferrer"> 下载服务端生成的PDF </a>
常见问题修复
- 中文乱码:确保已经注册中文字体,且所有用到文本的组件都指定了正确的fontFamily
- 客户端渲染报错:确认组件添加了
'use client'标记,或动态导入时关闭了SSR - 服务端生成报错:确认已经在
next.config.js中添加了@react-pdf/renderer作为服务端外部依赖
内容的提问来源于stack exchange,提问作者Nitish Kumar Patel
相关产品推荐
相关产品推荐

