在Vercel使用Puppeteer-core生成PDF时日文字符不显示的解决方法
在Vercel环境下解决Puppeteer生成PDF日文字符缺失问题
核心问题分析
Vercel的Serverless函数环境是无状态的干净系统,没有预装日文字体;同时字体加载是异步过程,若PDF生成时机过早,字体未加载完成就会导致日文字符完全不显示。以下是针对性解决方案:
方案一:确保字体文件正确部署并强制加载
部署字体文件
将Noto Sans JP的字体文件(推荐体积更小的woff2格式)放在Next.js的public/fonts目录下,确保构建后能通过绝对路径访问(如/fonts/NotoSansJP-Regular.woff2)。调整@font-face配置
用绝对路径指定字体源,加上font-display: block确保字体加载完成前不显示 fallback 内容,同时全局强制使用该字体:@font-face { font-family: 'Noto Sans JP'; src: url('/fonts/NotoSansJP-Regular.woff2') format('woff2'); font-weight: normal; font-style: normal; font-display: block; } * { font-family: 'Noto Sans JP', sans-serif !important; }Puppeteer中等待字体加载完成
在生成PDF前,通过page.waitForFunction确保字体已加载并可用:await page.goto('/your-pdf-page', { waitUntil: 'networkidle0' }); // 等待Noto Sans JP字体加载完成 await page.waitForFunction(async () => { const font = new FontFace('Noto Sans JP', 'url("/fonts/NotoSansJP-Regular.woff2")'); await font.load(); document.fonts.add(font); return document.fonts.check('16px "Noto Sans JP"'); }); // 生成PDF时开启printBackground确保样式生效 const pdfBuffer = await page.pdf({ format: 'A4', printBackground: true, });
方案二:给@sparticuz/chromium-min预安装字体
如果方案一仍无效,可直接将字体安装到Chromium的字体目录,让浏览器直接识别:
- 将字体文件放在项目的
assets/fonts目录下。 - 在启动Chromium前复制字体到其内置字体目录:
import chromium from '@sparticuz/chromium-min'; import puppeteer from 'puppeteer-core'; import fs from 'fs'; import path from 'path'; export async function generatePDF() { // 获取Chromium的可执行路径和字体目录 const chromiumPath = await chromium.executablePath(); const chromiumFontDir = path.join(chromiumPath.split('/').slice(0, -1).join('/'), 'fonts'); // 复制本地字体到Chromium字体目录 const localFontPath = path.join(process.cwd(), 'assets/fonts/NotoSansJP-Regular.ttf'); fs.copyFileSync(localFontPath, path.join(chromiumFontDir, 'NotoSansJP-Regular.ttf')); // 启动浏览器 const browser = await puppeteer.launch({ args: chromium.args, executablePath: chromiumPath, headless: chromium.headless, }); const page = await browser.newPage(); await page.goto('/your-pdf-page', { waitUntil: 'networkidle0' }); const pdfBuffer = await page.pdf({ format: 'A4', printBackground: true }); await browser.close(); return pdfBuffer; }
常见排查点
- 确认字体文件名和CSS中的字体名称完全一致(大小写敏感)。
- 检查Vercel部署日志,确保字体文件被正确上传到
public目录。 - 生成PDF时必须开启
printBackground: true,否则部分样式可能不渲染。
内容的提问来源于stack exchange,提问作者杉山航太
相关产品推荐
相关产品推荐

