不能用引入本地css文件,因puppeteer生成pdf时html为字符串动态渲染,无静态服务支持,相对路径易错乱;file://协议被chromium静默拦截,且express.static()无效,故推荐内联并确保utf-8编码、系统字体及资源内联。

直接在 HTML 字符串里写 <style></style>,别用 <link rel="stylesheet"> 加载外部 CSS 文件
为什么不能用 <link> 引入本地 CSS 文件
Puppeteer 生成 PDF 时会加载一个 URL(比如 /api/pdf/123),这个请求返回的 HTML 必须能离线渲染——浏览器(或无头 Chromium)不会去加载同目录下的 style.css,除非你配了完整的静态服务、正确设置了 base 标签、还确保所有相对路径不因路由层级错乱。而服务端生成 PDF 的典型场景是:HTML 是字符串拼出来的,或由模板引擎即时渲染的,压根没走文件系统静态托管那套。
常见错误现象:PDF 中文字没字体、布局错乱、flex 不生效、图标消失——八成是因为 CSS 没加载上,Chromium 静默失败,连 404 都不报。
- Express 的
express.static()对 Puppeteer 无效,除非你让 Puppeteer 访问的是带完整域名的公网 URL(比如http://localhost:3000/assets/style.css),但这就引入了跨域、网络延迟、服务未就绪等新问题 - 用
file://协议加载本地 CSS?Chromium 在无头模式下默认禁用file://跨资源加载,会直接被拦截 - 内联
<link href="/assets/style.css">?前提是你的 Express 路由必须同时暴露该静态路径,且 HTML 响应头Content-Type是text/html,否则可能触发 MIME 类型误判
推荐做法:CSS 内联进 HTML 字符串
把样式直接塞进 <style>...</style>,彻底绕过外部加载。这是最稳、最可控的方式,尤其适合动态内容+固定样式的 PDF 场景(如合同、报表、凭证)。
示例中关键点:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 使用
fs.readFileSync('./assets/style.css', 'utf8')读取 CSS 内容(注意路径是服务端文件系统路径,不是浏览器可访问路径) - 确保 CSS 里没依赖外部字体、图片等资源;如有,转为 base64 内联或换用系统字体(如
font-family: "SimSun", "Microsoft YaHei", sans-serif) - 避免使用
@import,它在内联<style></style>中无效 - 如果样式来自多个文件,手动合并或用构建脚本预处理(不要指望 Puppeteer 运行时解析)
代码片段示意:
const css = fs.readFileSync('./assets/pdf-style.css', 'utf8');
const html = `
<meta charset="UTF-8"><style>${css}</style>...
`;
如果必须复用前端 CSS,怎么安全提取
前端项目(Vue/React)的 CSS 通常带 scope、postcss 处理、CSS-in-JS 等,不能直接拷贝。要复用,得走构建环节导出纯净版:
- 用
mini-css-extract-plugin或extract-text-webpack-plugin把生产环境 CSS 单独打成一个文件(如pdf-bundle.css),再读取它 - 禁用所有需要运行时注入的特性:
:global、composes、CSS 变量(除非你用postcss-custom-properties静态替换) - 检查是否用了
background-image: url(...)——这类路径在服务端是无效的,要么删掉,要么替换成 data-url - 字体优先用系统自带(如
"PingFang SC","Helvetica Neue","Segoe UI"),避免引用@font-face,Puppeteer 不会下载远程字体文件
容易被忽略的细节:编码与字符集
中文 PDF 乱码?大概率不是字体问题,而是 HTML 缺少 <meta charset="UTF-8"> 或 CSS 文件本身保存为 GBK 编码。
- 确保
fs.readFileSync的第二个参数明确传'utf8',不要省略 - 编辑器里确认
.css文件是 UTF-8 无 BOM 格式(VS Code 底部状态栏可看,右键切换编码) - 如果用了 WebFont(如 iconfont),其字体文件路径在服务端不可达,图标会变成方块;改用 SVG 内联或 Unicode 字符替代
- Puppeteer 的
page.pdf()默认用 A4 尺寸和系统默认字体,不自动继承 CSS 中的font-family,所以必须在 body 或 root 元素显式声明
真正卡住人的,往往不是“怎么加 CSS”,而是“加了但没生效”——而失效原因 90% 出现在路径、编码、字体、资源外链这四个地方。盯住控制台日志(开启 dumpio: true)和生成的中间 HTML 文件,比反复调参数更有效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










