中文 | English
🎭 Playwright 实现, 基于 ESM + Koa + TypeScript + Rollup + Nodemon + PM2 + ESLint (v9) 快速构建网页转换 PDF、图片的 Node.js 中间件服务
能够将任意网页快速生成为 PDF、图片。
支持将多个网页合并,并最终生成一个 PDF 文件,支持 Cookies 的注入、PDF 水印的添加和页眉页脚的插入。
如果之前使用的 Puppeteer, 可以在这里找到旧版仓库:
Puppeteer 仓库: puppeteer-server
-
✅ 自带 TypeScript + ES Module 环境
-
🎨 解耦了业务层和控制层
-
🛡 可能是 Playwright 项目的最佳实践
-
🧩 可配置的路由
-
🧺 内置 Eslint (v9) 语法风格检查
-
⚡ 使用 Rollup 快速构建
-
🔌 内置了 PDF 水印、页眉和页脚,可自行修改及扩展
-
🖇️ 支持合并多个 PDF 文件
-
🔥 支持 Nodemon 开发环境下的模块热更新
- 示例:合并多个网站到一个 PDF 文件
请确保安装了 Node.js(>= 20.x)
├── src │ ├── controllers/ --- 控制层,负责调用业务层的接口 │ ├── services/ --- 业务层,负责编写具体的业务代码 │ ├── config.ts --- 用于导出一些全局变量 │ ├── main.ts --- 入口文件 │ └── routes.ts --- 用于配置路由元信息 👉 路由配置
pnpm install
pnpm dev
该项目已内置 pm2
,在构建完毕后运行 pnpm start
即可使用 pm2
管理进程。
运行 pnpm build
进行构建,然后运行 pnpm start
启动由 pm2
管理的进程:
- 打包构建
pnpm build
- 运行
pnpm start # 端口号为 8080
# 或直接运行
node dist/bundle.esm.js # 端口号为 5000
GET /image
用于生成一张图片
curl --location --request GET \
'http://localhost:5000/image?url=https://www.baidu.com' \
--output test-baidu-image.png
curl --location --request GET \
'http://localhost:5000/image?url=https://www.google.com' \
--output test-google-image.png
GET /simple-pdf
用于生成一个 PDF 文件
curl --location --request GET \
'http://localhost:5000/simple-pdf?url=https://www.google.com/' \
--output test-simple-pdf.pdf
POST /pdf
可生成一个带有自定义页眉和页脚的 PDF(页眉页脚的内容可通过参数来控制是否显示)
curl --location --request POST 'http://localhost:5000/pdf' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'url=http://www.google.com' \
--data-urlencode 'cookies[0].name=token' \
--data-urlencode 'cookies[0].value=9s2d4c16-f072-16eg-b134-0642ap190006' \
--data-urlencode 'cookies[0].path=/' \
--data-urlencode 'cookies[0].domain=www.google.com' --output test-complex-pdf.pdf
👆 /pdf 请求参数
字段 | 说明 | 类型 | 默认值 |
---|---|---|---|
url | 目标网站 | string | — |
cookies | 如果网站需要提前内置 sessionId cookie, 一般用作需要登录校验才能访问的网站,则添加此字段即可 | Array<{ name, value, domain }> | [] |
hasMargin | 是否生成出的 PDF 含有内边距空白 | boolean | true |
isLandscape | 是否生成横向的 PDF | boolean | false |
hiddenWatermark | 是否隐藏水印 | boolean | false |
attachment | 展示自定义页眉页脚,前提是需要将 hasMargin 设置为 true | { header, footer } | — |
POST /combine-pdf
用于将多个 PDF 文件合并到一个文件
👆 /combine-pdf 请求参数
字段 | 说明 | 类型 | 默认值 |
---|---|---|---|
pdfList | 目标网站集合,参数类型为数组,数组内每一项即为一个 /pdf 所需的参数 |
Array<{ pdfItem }> | [] |
为了使路由元数据更具可读性和透明性,这里采用了配置化的方式
你可以创建一个 数组
,然后将路由元信息写入该 数组
中,并在 src/routes.ts 中重用它
const routes: Array<RouteConfig> = [
{
path: '/',
method: 'get',
action: homeController.hello
},
// here...
]
✌️