在Heroku上使用html-pdf-node库失败的问题排查与解决
问题描述
在Node.js中使用html-pdf-node库将HTML转换成PDF Buffer,作为邮件附件通过Nodemailer发送。本地环境运行正常,但部署到Heroku dyno时出现报错,提示无法启动浏览器进程,缺少libnss3.so共享库。
相关代码:
const file = { content: attachementPdfContentString }; return htmlToPdf.generatePdf(file, options).then(pdfBuffer => { try { return this.sendMail({ to: hotelEmail, subject: "Dashback Invoice", body: `Hi `, attachments: [ { filename: 'invoice.pdf', content: Buffer.from(pdfBuffer, 'utf-8') } ] }); } catch (err) { console.error("Unable to send mail for hotel invitation", JSON.stringify(invoice)); throw err; }
错误日志
2022-11-29T15:43:13.506732+00:00 app[web.1]: Error: Failed to launch the browser process! 2022-11-29T15:43:13.506734+00:00 app[web.1]: /app/node_modules/puppeteer/.local-chromium/linux-901912/chrome-linux/chrome: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory 2022-11-29T15:43:13.506734+00:00 app[web.1]: 2022-11-29T15:43:13.506734+00:00 app[web.1]: 2022-11-29T15:43:13.506735+00:00 app[web.1]: TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md 2022-11-29T15:43:13.506735+00:00 app[web.1]: 2022-11-29T15:43:13.506735+00:00 app[web.1]: at onClose (/app/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserRunner.js:197:20) 2022-11-29T15:43:13.506736+00:00 app[web.1]: at Interface.<anonymous> (/app/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserRunner.js:187:68) 2022-11-29T15:43:13.506736+00:00 app[web.1]: at Interface.emit (node:events:525:35) 2022-11-29T15:43:13.506737+00:00 app[web.1]: at Interface.close (node:internal/readline/interface:536:10) 2022-11-29T15:43:13.506738+00:00 app[web.1]: at Socket.onend (node:internal/readline/interface:262:10) 2022-11-29T15:43:13.506738+00:00 app[web.1]: at Socket.emit (node:events:525:35) 2022-11-29T15:43:13.506738+00:00 app[web.1]: at endReadableNT (node:internal/streams/readable:1359:12) 2022-11-29T15:43:13.506739+00:00 app[web.1]: at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
解决方案
1. 添加Heroku Puppeteer Buildpack
Heroku默认环境缺少Chromium运行所需的系统依赖,添加专用buildpack可自动安装这些依赖:
- 进入Heroku应用的
Settings页面,找到Buildpacks区域 - 点击
Add buildpack,输入地址:https://github.com/jontewks/puppeteer-heroku-buildpack.git - 调整buildpack顺序,确保该buildpack在Node.js buildpack之前
- 重新部署应用
2. 手动指定系统依赖(通过Aptfile)
若不想用专用buildpack,可通过Aptfile手动声明依赖:
- 在项目根目录创建
Aptfile,写入以下内容:
libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2 libpangocairo-1.0-0 libpango-1.0-0 libcairo2 libatspi2.0-0 libx11-6 libxcb1 libxext6
- 添加Heroku的Apt buildpack:
https://github.com/heroku/heroku-buildpack-apt.git - 重新部署应用,系统会自动安装这些依赖
3. 配置浏览器启动参数
在html-pdf-node的配置选项中添加无头模式和沙箱禁用参数,避免权限问题:
const options = { format: 'A4', args: ['--no-sandbox', '--disable-setuid-sandbox', '--headless=new'] };
替代方案
若上述方法仍无法解决,可更换HTML转PDF的实现方式:
- html-pdf:基于wkhtmltopdf,无需浏览器环境,但该库已停止维护,仅适合简单场景
- node-wkhtmltopdf:直接调用wkhtmltopdf工具,需在Heroku安装对应buildpack,稳定性较好
- PDFKit:纯Node.js生成PDF,需手动构建文档内容,适合定制化需求,无外部依赖
- 云转换服务:将HTML发送到第三方API生成PDF后返回Buffer,避免在Heroku处理浏览器依赖问题
内容的提问来源于stack exchange,提问作者Code Guru
相关产品推荐
相关产品推荐

