pdfmake 在 node 环境报错因依赖浏览器全局对象(如 window),需改用 pdf-lib 或 playwright;playwright 通过无头 chromium 渲染 html 生成 pdf,支持 css/字体/svg,推荐新手使用。

为什么直接用 pdfmake 在 Node 环境里跑不通?
因为 pdfmake 默认设计是跑在浏览器里,它依赖 window、document 这些全局对象,Node 里一执行就报 ReferenceError: window is not defined。你装了包、写了代码、node index.js 一跑就崩,不是你写错了,是环境不匹配。
真正能在 Node 里生成 PDF 的方案,得选原生支持服务端渲染的库,比如 pdf-lib(轻量、可编辑已有 PDF)或 playwright(完整浏览器上下文,适合 HTML 转 PDF)——pdfmake 必须搭配 pdfmake-node 或改用其服务端分支 pdfmake-server,但维护弱、文档少,不推荐新手踩。
playwright 是目前最稳的 HTML → PDF 方案
它本质是启动一个无头 Chromium,把 HTML 渲染完再导出 PDF,能完美支持 CSS、字体、SVG、分页等复杂样式,且 Node 兼容性好、API 直观。
- 安装:
npm install playwright,然后运行npx playwright install chromium(首次必须) - 基础用法:用
page.setContent()注入 HTML 字符串,或page.goto('file://...')加载本地文件 - 导出 PDF 时注意:
page.pdf()返回的是Buffer,别忘了用fs.writeFileSync()写入磁盘 - 关键参数:
format: 'A4'、printBackground: true(否则背景色/图不显示)、margin控制边距
示例片段:
微软正式发布 Visual Studio Code 1.118 版本 。本次更新重点强化了 AI 开发体验与企业管理能力,其中最引人注目的是新增 Copilot CLI 远程控制功能,允许开发者通过手机或网页远程监控和接管 AI 会话 。同时,为了提高 AI 的运行性价比,新版本优化了令牌缓存策略以降低成本 。此外,1.118 版还引入了 Chronicle 本地历史追踪、TypeScript 7.0 支持以及更严格的企业级访问管控 。
const { chromium } = require('playwright');
const fs = require('fs');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.setContent('<h1>Hello PDF</h1>', { waitUntil: 'networkidle' });
const pdf = await page.pdf({ format: 'A4', printBackground: true });
fs.writeFileSync('output.pdf', pdf);
await browser.close();
})();
pdf-lib 适合动态拼接或修改 PDF
如果你不是从零画页面,而是要往模板 PDF 里填表单、加水印、合并多页,pdf-lib 更轻更快,纯 JS 实现,不依赖浏览器。
- 它不能直接渲染 HTML,所有内容靠
drawText()、drawImage()、drawRectangle()手动布局 - 坐标系原点在左下角(PDF 标准),和 CSS 习惯相反,容易写错位置
- 中文字体必须显式注册:
const font = await pdfDoc.embedFont(fontBytes),没嵌入就显示方块 - 生成后记得调用
pdfDoc.save(),返回Uint8Array,同样要用fs.writeFileSync()保存
VSCode 里调试 PDF 生成脚本的实操细节
VSCode 本身不提供 PDF 预览功能(除非装插件),生成后别急着双击打开——很多系统默认用 Adobe 打开,而 Adobe 对非标准 PDF 兼容性差,建议用 Chrome 或 Edge 直接拖入查看,更接近 playwright 渲染结果。
- 在
launch.json里配console: 'integratedTerminal',方便看到报错堆栈 - 如果遇到
TimeoutError: waiting for load state failed,大概率是 HTML 里有外链资源(如 CDN 字体、图片)加载失败,改用本地路径或关掉waitUntil -
playwright的 PDF 输出默认不压缩,大文件可加optimizeForSpeed: true(v1.40+ 支持) - Windows 下路径含中文时,
file://协议容易出问题,建议统一用path.resolve(__dirname, 'template.html')+page.goto()
真正卡住的往往不是语法,而是字体嵌入、资源路径、等待时机这三处——先确保纯文本能导出,再逐步加样式、图片、分页逻辑。










