大家好,我是CC,在这里欢迎大家的到来~
“当你的前端项目需要一个PDF生成功能时,面对众多的技术方案,你会如何抉择?是选择看似简单的html2canvas + jspdf组合,还是功能强大但学习曲线稍高的pdfmake,或是其他服务端方案?
这个决策的关键,往往在于对开发体验、样式控制能力、复杂度与性能的权衡。为了找到这个问题的答案,我深入调研和实践了目前主流的前端PDF生成方案。本文将为你进行一次全面的对比分析,并最终阐述为什么在大多数纯前端场景下,pdfmake成为了我的首选推荐。”
方案对比
首先我们对比下各个方案的优劣势。
window.print
获取 body 下内容,触发 window.print 另存为 PDF。
优势
- 改动小,实现快速
劣势
- 网页内容会被改变,体验不好
- 不够高级
jsPDF
创建 PDF 文件,添加元素;也可以将 DOM 节点转 PDF。
优势
- 掌控写入 PDF 的内容
- 不会出现分页字被分割的问题
劣势
- 需要引入字体文件,但由于字体文件过大会导致用户体验差
- DOM 节点转 PDF 效果差,会丢失大量样式
- 表格图片变形
html2canvas + jsPDF
将 DOM 节点转化成图片在转化成 PDF。
优势
- 改动小,实现快
劣势
- 相当于放了图片在 PDF 里,会失真
- 在图片超出 PDF 页面大小时缩小展示
- PDF 可搜索复制功能丢失
pdfmake
创建 PDF 文件,添加元素;结合 html-to-pdfmake 可将 DOM 节点转 PDF。
优势
- 写入的 PDF 内容可掌控
- 解决分页截断处理较好
劣势
- 需要导入字体文件,但由于字体文件过大会导致用户体验差
- 代码量相对较多
pdfmake使用
步骤
- pnpm i pdfmake
- 找个想要的字体(字体库) 例如导入字体 NotoSansSC-Regular.ttf
- 下载放到 node_modules/examples/fonts
- 打开 node_modules 下 pdfmake 文件夹的终端
- 运行
node build-vfs.js "./examples/fonts"
- 使用
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
pdfMake.vfs = pdfFonts.pdfMake.vfs;
pdfMake.fonts = {
NotoSansSC: {
normal: `${window.location.origin}/assets/NotoSansSC-Regular.ttf`,
bold: `${window.location.origin}/assets/NotoSansSC-Bold.ttf`,
},
};
const docDefinition: any = {
pageMargins: [ 40, 60, 40, 60 ],
content, // 写入的内容
pageSize: 'A4',
defaultStyle: {
// 设置定义的字体为默认字体
font: 'NotoSansSC',
fontSize: 16,
bold: true,
},
styles: {
header: {
background: '#f2f2f2',
bold: true,
width: '100%',
alignment: 'center',
margin: [ 0, 0, 0, 10 ],
},
table: {
fontSize: 12,
bold: false,
margin: [ 0, 0, 0, 10 ],
},
sub_title: {
fontSize: 12,
bold: false,
margin: [ 0, 0, 0, 10 ],
},
text: {
fontSize: 12,
bold: false,
margin: [ 0, 0, 0, 10 ],
},
},
};
// 测试用
// const win = window.open('', '_blank');
// pdfMake.createPdf(docDefinition).open({}, win);
pdfMake.createPdf(docDefinition).download('分析报告', () => {
this.message.success('下载成功');
});
存在的问题
- 字体导入方式存在问题。
- 根据文档看 VFS 虚拟文件系统目前(v0.2.8,现已实现)没有实现,Http 协议方式会更加推荐使用。
- Http 导入字体,因为字体文件较大且可能会同时使用一个字体的多个文件(像 Regular、Bold),使用体验不好。
优化方式
- 在生成 PDF 及下载字体时给用户反馈,表示正在下载中。
- 预加载字体文件。
- 对字体文件进行过滤,只需要文档中文字对应的内容。
总结
当然 pdfmake 不止这些优势,更多功能大家有业务有需求时去探索探索吧。