需求是输入 HTML 文件或 URL,输出 PDF 文件。

当然有相应的 Node.js package,还不少。不过有些功能太强,整套 PDF 工具箱;有些需额外安装组件,package 只是套个壳;有些文档太复杂/太简单看不明白;有些太久没有更新,挺简单的要求,找个合适的工具挺花时间。

(Chrome) 浏览器的打印功能早就有 Save as PDF 选项,日常我就是这样生成需要的 PDF 文件,现在不过是需要对这个动作进行编程以省去些手工操作,所以最后选择了 html-pdf-chrome - npm

代码很简单

const htmlPdf = require("html-pdf-chrome");

const url = "https://github.com/westy92/html-pdf-chrome";

const options = {
  port: 9222 // port Chrome is listening on
};

htmlPdf
  .create(url, options)
  .then(pdf => pdf.toFile("test.pdf"))
  .catch(err => console.log(err));

运行会返回错误:Error: connect ECONNREFUSED 127.0.0.1:9222

文档建议运行程序时保持 Chrome 开启,但是程序调用的是 Headless Chrome。

Headless Chrome is a way to run the Chrome browser in a headless environment without the full browser UI. One of the benefits of using Headless Chrome (as opposed to testing directly in Node) is that your JavaScript tests will be executed in the same environment as users of your site. Headless Chrome gives you a real browser context without the memory overhead of running a full version of Chrome.

也就是说需要你自己先启动一个 Headless Chrome 实例,或者用 pm2 运行,提高程序效率,如奔溃会自动重启。

如果偶尔用用,不想麻烦,把 options 对象里 port: 9222 删掉。它的逻辑是这样的,如果你指定了主机或端口,程序假设 Chrome 已经在该主机/端口运行。如果不指定,程序会启动自己的 Chrome 实例,运行完成后关闭。(开着有头 Chrome 折腾半天,我……)