You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Vercel使用Puppeteer-core生成PDF时日文字符不显示的解决方法

在Vercel环境下解决Puppeteer生成PDF日文字符缺失问题

核心问题分析

Vercel的Serverless函数环境是无状态的干净系统,没有预装日文字体;同时字体加载是异步过程,若PDF生成时机过早,字体未加载完成就会导致日文字符完全不显示。以下是针对性解决方案:

方案一:确保字体文件正确部署并强制加载

  1. 部署字体文件
    将Noto Sans JP的字体文件(推荐体积更小的woff2格式)放在Next.js的public/fonts目录下,确保构建后能通过绝对路径访问(如/fonts/NotoSansJP-Regular.woff2)。

  2. 调整@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;
    }
    
  3. 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的字体目录,让浏览器直接识别:

  1. 将字体文件放在项目的assets/fonts目录下。
  2. 在启动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,提问作者杉山航太

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 21:46:00