【免费下载链接】dompdf.js
HTML to PDF in the browser — one line of code for selectable, searchable vector PDFs (10,000+ pages). Pure frontend: zero backend, zero runtime deps. TypeScript over a Rust + WebAssembly engine; an html2canvas/jsPDF alternative.
dompdf.js是一个纯前端的浏览器端 HTML 转 PDF 引擎:它直接读取浏览器已计算好的 DOM 布局,在浏览器内生成可选中、可搜索的矢量 PDF。零后端、无 jsPDF 依赖,一行代码即可导出,500 页文档典型耗时约 2 秒,极限可扩到上万页。
它是什么?为什么值得用?
传统的「HTML 转 PDF」方案大多依赖html2canvas + jsPDF:先把整个页面截图成 Canvas,再拼进 PDF。结果就是——文字变成了图片:不可选、不可搜索,文件还特别大。
dompdf.js换了一条路:
不截图,而是读取浏览器已经算好的布局几何信息,重新「画」出一份以矢量文本为主的 PDF。
这意味着:
- ✅ 文本可复制、可搜索、可放大不失真
- ✅ 整份文档不经过服务器,隐私零上传
- ✅ 长文档性能强:典型测试约 2 秒生成 500 页
- ✅ 自带页眉页脚、水印、中文字体、表单、加密等导出刚需能力
一句话定位:它是 html2canvas/jsPDF 的替代方案,也是目前少有的「纯前端 + Rust/WASM」矢量 PDF 引擎。
功能清单:一张表看懂能力
| 能力 | 说明 |
|---|---|
| 📄 分页与纸张 | A/B/C 系列、Letter、Legal、Tabloid 及自定义尺寸 |
| 📑 页眉页脚 | 页码占位符${currentPage}/${totalPages}、逐页不同配置 |
| 💧 水印 | 文字/图片水印,角度、透明度、上下层叠放、逐页控制 |
| 🔤 中文与自定义字体 | TTF 嵌入、字体子集、语言区间回退(langFontConfig) |
| 🖼️ 视觉效果 | 图片、SVG、Canvas、背景、圆角、阴影、渐变、透明度 |
| 🔗 超链接 | 自动转为 PDF 链接注释 |
| 📝 表单导出 | 静态外观 + 可交互 AcroForm 字段(hybrid模式) |
| 🔒 加密与压缩 | 用户/所有者密码、权限控制、DEFLATE 压缩 |
| 📊 进度回调 | onProgress返回采集、计页、渲染、完成四个阶段 |
完整选项表见 README_CN.md,页面尺寸速查表见 page_sizes.md。
工作原理:5 步生成 PDF
dompdf.js的流水线由TypeScript + Web Worker + Rust/WASM三层协作完成:
- 主线程采集——遍历目标元素,读取浏览器计算后的布局、样式、文本、图片和表单状态;
- 编码快照——TypeScript 把采集结果编码成紧凑的二进制快照;
- 转移给 Worker——快照通过可转移对象发送到 Web Worker,主线程不被阻塞;
- Rust/WASM 渲染——完成分页、字体子集、绘制和 PDF 对象写入;
- 回传结果——主线程拿到 PDF 字节,返回
Blob/Uint8Array或触发下载。
这套结构的关键优势:不先把整份文档画成一张 Canvas,把最重的 PDF 生成工作移出主线程,所以长文档导出不卡顿。
- 前端采集与快照:src/snapshot.ts、src/worker.ts
- Rust 渲染层:wasm/src/paginate.rs、wasm/src/font.rs、wasm/src/encrypt.rs、wasm/src/deflate.rs
快速上手:两种安装方式
方式一:npm 安装(推荐)
npm install dompdf.js运行环境需要支持 Web Workers、WebAssembly 的现代浏览器;构建开发需要 Node.js 18+。
方式二:CDN 一行引入
<script src="https://cdn.jsdelivr.net/npm/dompdf.js@latest/dist/dompdf.min.js"></script>引入后 API 挂载在全局dompdf上,适合快速验证。
一行代码生成 PDF:最小示例
获取 PDF 的Blob(用于预览、上传或自定义下载):
import dompdf from 'dompdf.js'; const element = document.querySelector<HTMLElement>('#capture'); const blob = await dompdf(element, { format: 'a4', pagination: true, backgroundColor: '#ffffff', }); const url = URL.createObjectURL(blob); window.open(url, '_blank');更省事的一键下载:
import { downloadPDF } from 'dompdf.js'; await downloadPDF(element, { format: 'a4', pagination: true, compress: true, }, 'report.pdf');常用 API 一览:
| API | 返回值 | 适用场景 |
|---|---|---|
dompdf(root, options?) | Blob | 默认入口,预览/自定义流程 |
exportPDF(root, options?) | Blob | 同上,语义更明确 |
renderToBytes(root, options?) | Uint8Array | 上传接口、File System API |
downloadPDF(root, options?, filename?) | 触发下载 | 一键导出按钮 |
inspect(root, options?) | 快照摘要 | 诊断节点/图片/字体/页数 |
完整 TypeScript 类型定义见 src/snapshot.ts。
实战技巧:长尾功能速查
📑 分页与强制换页
pagination: true按页面可用高度自动分页;想手动控制换页位置,给元素加属性即可:
<section pageBreak>从新的一页开始</section> <article divisionDisable>尽量保持在本页完整显示</article>横向 A4 直接传自定义尺寸:format: [842.25, 595.5]。
📑 页眉页脚与页码
pageConfig: { excludePages: [1], // 第一页不显示 footer: { content: 'Page ${currentPage} / ${totalPages}', height: 48, contentPosition: 'center', }, }还支持pageConfig(pageNum, totalPages)函数形式,每页返回不同配置(比如奇偶页水印不同)。
💧 文字水印
watermark: { text: 'INTERNAL ${currentPage}', color: 'rgba(185, 28, 28, 0.14)', angle: -35, spacing: [180, 130], layer: 'under', }🔤 中文字体:避免空白和方框
浏览器字体不会自动嵌入 PDF,中文文档必须显式注册 TTF:
const fontBuffer = await fetch('/fonts/SourceHanSansSC-Regular.ttf') .then((r) => r.arrayBuffer()); await dompdf(element, { fontConfig: { fontFamily: 'SourceHanSansSC-Regular', // 与 CSS font-family 一致 fontBytes: new Uint8Array(fontBuffer), fontWeight: 400, }, });多语言混排可用langFontConfig按 Unicode 区间选择字体并设置默认回退。仓库内置示例字体加载脚本,如 examples-main/SourceHanSansCNNormal-normal.js。
🔒 加密与文档属性
encryption: { userPassword: 'reader-password', ownerPassword: 'owner-password', userPermissions: ['print', 'copy'], }, metadata: { title: 'Quarterly Report', author: 'Alice', keywords: ['report', 'finance'], }加密由 Rust 层实现,源码见 wasm/src/encrypt.rs。
📈 导出进度反馈
onProgress(progress) { if (progress.stage === 'rendering') { console.log(`渲染中:${progress.currentPage}/${progress.totalPages}`); } }四个阶段:collecting→countingPages(按需)→rendering→done,非常适合做导出进度条。
常见问题(FAQ)
❓ 中文显示为空白或方框?通过fontConfig.fontBytes注册含相应字符的 TTF 字体,并保证元素 CSSfont-family与fontFamily一致。
❓ 分页位置和浏览器预览不一致?把导出容器宽度调到接近目标纸张内容宽度(A4 ≈ 794px @ 96DPI,需扣除页边距),导出前等待字体和图片加载完成。
❓ 跨域图片没出现在 PDF 里?设置useCORS: true,并确认图片服务器返回Access-Control-Allow-Origin——前端选项无法绕过服务器限制。
❓ 如何减小 PDF 体积?开启compress: true、避免使用远超显示尺寸的大图、适当降低jpegQuality、只注册实际用到的字体和字重。
❓ 能跑在 Node.js / SSR 里吗?不能直接采集页面(依赖 DOM),Next.js、Nuxt 等 SSR 项目请在客户端调用导出 API。
从 html2canvas + jsPDF 迁移过来?
项目已从旧的html2canvas + jsPDF流水线迁移到DOM 快照 + Worker + WASM。旧参数大多被接受(部分会输出 warning)以平滑过渡,完整对照见迁移说明:
- 中文:docs/migration-compat.zh-CN.md
- 英文:docs/migration-compat.md
建议升级路径:先升级版本保留旧参数 → 观察 warning 确认哪些只是兼容签名 → 把依赖 jsPDF 实例的定制逻辑迁到导出前后处理 → 状态反馈统一切到onProgress。
⚠️ 已知边界:动画、视频、iframe 无法完整动态导出;复杂滤镜/遮罩可能被降级或栅格化;它不是完整浏览器渲染引擎。
本地开发与项目结构
rustup target add wasm32-unknown-unknown npm install npm run build # 构建发布包 npm test # 构建 WASM 并运行 PDF 冒烟验证 npm run serve # 8080 端口启动示例服务验证脚本 scripts/verify.mjs 会检查基础分页、PDF 结构、图片、中文字体子集等核心链路。
dompdf.js/ ├── src/ # TypeScript API、DOM 采集、Worker 和 WASM 桥接 ├── wasm/ # Rust 分页、字体、压缩、加密和 PDF 写入器 ├── examples-main/ # 浏览器演示页面和示例字体 ├── docs/ # 迁移说明与 PDF 差异系统文档 └── scripts/ # 构建、验证和 PDF 差异工具写在最后
如果你需要一个不上传数据、文本可选中、长文档不卡死的浏览器端 HTML 转 PDF 方案,dompdf.js目前的组合拳——TypeScript API + Web Worker + Rust/WASM 矢量渲染,再加上水印、页眉页脚、中文字体、加密压缩这些导出刚需——相当完整。
💬 欢迎加入维护交流群交流实战问题:
项目基于 MIT License 开源,变更记录见 CHANGELOG.md,参与贡献前请阅读 CONTRIBUTING.md。
【免费下载链接】dompdf.js
HTML to PDF in the browser — one line of code for selectable, searchable vector PDFs (10,000+ pages). Pure frontend: zero backend, zero runtime deps. TypeScript over a Rust + WebAssembly engine; an html2canvas/jsPDF alternative.
相关推荐
Kokoro-82M:如何在资源受限环境中部署高性能TTS模型
Kokoro 82M:如何在资源受限环境中部署高性能TTS模型 面对TTS模型部署时常见的资源瓶颈——庞大的模型体积、缓慢的推理速度、复杂的依赖环境,开发者往往
人工智能语音音频极简SVG转PDF:浏览器端矢量图无损转换全攻略
极简SVG转PDF:浏览器端矢量图无损转换全攻略 在当今前端开发中, SVG转PDF 的需求日益增长,无论是将网页图表导出为报告,还是将矢量图形保存为可打印文档
图形学如何用jsPDF实现浏览器端PDF生成?开发者必备的零后端创新指南
如何用jsPDF实现浏览器端PDF生成?开发者必备的零后端创新指南 在现代Web开发中,浏览器端PDF生成已成为提升用户体验的关键功能。jsPDF作为一款强大的
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考