Node.js中不使用Puppeteer转带样式HTML为PDF遇jsPDF报错
解决jsPDF生成PDF时'document is not defined'错误
错误原因
你遇到的document is not defined本质是jsPDF的html()方法依赖浏览器环境的DOM对象,如果代码运行在Node.js后端环境(而非浏览器前端),Node没有原生的document对象,就会触发这个错误。你之前用的Puppeteer是通过模拟浏览器实例处理DOM,所以不会有这个问题,但jsPDF默认的html()方法不支持纯Node环境。
可行替代方案
方案1:用jsdom+html2canvas+jsPDF在Node环境模拟DOM
通过jsdom创建模拟的浏览器DOM环境,结合html2canvas将HTML转为canvas,再用jsPDF生成PDF。
- 安装依赖:
npm install jsdom html2canvas jspdf
- 示例代码:
const { JSDOM } = require('jsdom'); const html2canvas = require('html2canvas'); const jsPDF = require('jspdf'); async function generatePDF() { // 获取要转换的HTML内容 const html = await this.generateTablePDF(); // 创建模拟DOM环境 const dom = new JSDOM(html, { runScripts: 'dangerously', resources: 'usable' }); global.document = dom.window.document; global.window = dom.window; // 将HTML转为canvas const canvas = await html2canvas(document.body); // 用jsPDF生成PDF const doc = new jsPDF('p', 'mm', 'a4'); const imgData = canvas.toDataURL('image/png'); const pageWidth = doc.internal.pageSize.getWidth(); const pageHeight = doc.internal.pageSize.getHeight(); const imgWidth = canvas.width; const imgHeight = canvas.height; const ratio = Math.min(pageWidth / imgWidth, pageHeight / imgHeight); const scaledWidth = imgWidth * ratio; const scaledHeight = imgHeight * ratio; doc.addImage(imgData, 'PNG', 0, 0, scaledWidth, scaledHeight); // 输出为arraybuffer const pdfBase64 = await doc.output('arraybuffer'); // 清理全局变量 delete global.document; delete global.window; return pdfBase64; }
方案2:用html-pdf-node(更简洁的Node专用库)
这个库封装了无头浏览器逻辑(基于puppeteer-core),不需要手动处理DOM,直接传入HTML即可生成PDF,适合后端场景。
- 安装依赖:
npm install html-pdf-node
- 示例代码:
const html_to_pdf = require('html-pdf-node'); async function generatePDF() { const html = await this.generateTablePDF(); const options = { format: 'A4' }; const file = { content: html }; // 生成PDF buffer const pdfBuffer = await html_to_pdf.generatePdf(file, options); return pdfBuffer; }
注意事项
- 如果代码在浏览器前端运行,确保jsPDF和其依赖脚本正确加载(比如通过CDN引入
jspdf.umd.min.js和html2canvas.min.js),document对象会自动存在。 - 带样式的HTML表格要确保样式内联(用
style属性),或者在模拟DOM时正确加载样式文件,否则转换后的PDF可能丢失样式。
内容的提问来源于stack exchange,提问作者Alvaro Iglesias
相关产品推荐
相关产品推荐

