Node.js环境使用jsPDF的html方法报ReferenceError: document未定义
Node.js环境使用jsPDF生成PDF报错ReferenceError: document is not defined的解决办法
问题描述
在Node.js环境中使用jsPDF的html()方法从HTML模板生成PDF时,触发以下错误:
ReferenceError: document is not defined
相关代码:
generatePdf(formEntryId: string, customerId: string): ArrayBuffer { const template = this.templateService.getTemplate('testPdf') const doc = new jsPDF() doc.html(template, { callback: function (doc) { doc.save('testFile.pdf') } }) return doc.output('arraybuffer') }
错误原因
jsPDF的html()方法内部依赖浏览器环境的document对象解析、渲染HTML内容,但Node.js作为服务端运行环境不存在浏览器DOM对象,因此触发该错误。同时原代码存在异步问题:doc.html()是异步操作,直接在其后返回doc.output()会得到未完成渲染的空白PDF。
解决方案
方案一:使用Puppeteer(推荐,支持复杂HTML/CSS)
Puppeteer是无头Chrome工具,可完整模拟浏览器环境渲染HTML,生成的PDF兼容性和还原度更高。
- 安装依赖:
npm install puppeteer
- 修改代码(改为异步函数):
async function generatePdf(formEntryId: string, customerId: string): Promise<ArrayBuffer> { const template = this.templateService.getTemplate('testPdf'); // 启动无头浏览器 const browser = await puppeteer.launch({ headless: 'new' }); const page = await browser.newPage(); // 加载HTML模板 await page.setContent(template); // 生成PDF,开启背景渲染确保样式完整 const pdfBuffer = await page.pdf({ format: 'A4', printBackground: true }); await browser.close(); // 转换为ArrayBuffer返回 return pdfBuffer.buffer as ArrayBuffer; }
方案二:使用jsdom模拟DOM环境(适合简单HTML)
通过jsdom模拟浏览器DOM环境,配合canvas库让jsPDF可解析HTML。
- 安装依赖:
npm install jsdom jspdf canvas
- 修改代码:
import jsPDF from 'jspdf'; import { JSDOM } from 'jsdom'; import canvas from 'canvas'; // 注入模拟的浏览器环境 const dom = new JSDOM(''); global.document = dom.window.document; global.window = dom.window as any; global.HTMLCanvasElement = canvas.HTMLCanvasElement; async function generatePdf(formEntryId: string, customerId: string): Promise<ArrayBuffer> { const template = this.templateService.getTemplate('testPdf'); const doc = new jsPDF(); // 等待HTML渲染完成 await doc.html(template); // 生成并返回ArrayBuffer return doc.output('arraybuffer'); }
注意事项
- Node.js环境中无法直接使用
doc.save()触发浏览器下载,需将PDF的Buffer/ArrayBuffer返回给前端,由前端处理下载逻辑。 - 若HTML模板包含外部资源(如CSS、图片),需确保资源可被Puppeteer或jsdom访问(本地资源用绝对路径,远程资源确保网络可达)。
内容的提问来源于stack exchange,提问作者user2450639
相关产品推荐
相关产品推荐

