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

Firebase Function中Puppeteer找不到Chrome的优化方案咨询

Firebase Functions中Puppeteer生成PDF的优化方案(解决Chrome找不到+重复下载问题)

针对你遇到的Puppeteer在Firebase Functions中找不到Chrome、重复下载Chromium的问题,以下是几个适配Firebase环境的实用解决方案:

方案1:使用Puppeteer Core + Firebase预装Chromium

Firebase Functions的Node.js 16环境默认预装了Chromium,直接利用这个预装版本即可避免下载和体积过大问题,步骤如下:

  1. 替换依赖:卸载puppeteer,安装同版本的puppeteer-core
npm uninstall puppeteer
npm install puppeteer-core@19.3.8
  1. 修改代码,指定预装Chromium的路径:
import puppeteer from 'puppeteer-core';
import * as functions from 'firebase-functions';

async function generatePDF(htmlContent: string): Promise<Buffer> {
  // Firebase Node16环境中Chromium的固定路径
  const executablePath = '/usr/bin/chromium-browser';
  
  const browser = await puppeteer.launch({
    headless: 'new',
    args: [
      '--no-sandbox', 
      '--disable-setuid-sandbox',
      '--disable-dev-shm-usage' // 解决Firebase内存不足问题
    ],
    executablePath: executablePath,
  });

  functions.logger.log('browser.version()', await browser.version());

  const page = await browser.newPage();
  await page.setContent(htmlContent, { waitUntil: 'domcontentloaded' });
  const pdfBuffer = await page.pdf({ format: 'A4' });

  await browser.close();
  return pdfBuffer;
}

这个方案无需额外下载浏览器,函数体积小,执行效率最高。

方案2:缓存Chromium到临时目录(适配版本不匹配场景)

如果预装Chromium版本与Puppeteer不兼容,可将Chromium缓存到Firebase Functions的/tmp临时目录,减少重复下载:

import puppeteer from 'puppeteer';
import * as functions from 'firebase-functions';
import { join } from 'path';

async function generatePDF(htmlContent: string): Promise<Buffer> {
  // 指定缓存目录到/tmp,复用已下载的Chromium
  const browser = await puppeteer.launch({
    headless: 'new',
    args: [
      '--no-sandbox', 
      '--disable-setuid-sandbox',
      '--disable-dev-shm-usage'
    ],
    executablePath: await puppeteer.executablePath({
      cacheDirectory: join('/tmp', '.puppeteer_cache'),
    }),
  });

  functions.logger.log('browser.version()', await browser.version());

  const page = await browser.newPage();
  await page.setContent(htmlContent, { waitUntil: 'domcontentloaded' });
  const pdfBuffer = await page.pdf({ format: 'A4' });

  await browser.close();
  return pdfBuffer;
}

/tmp目录在函数执行后可能保留一段时间,后续调用可直接复用缓存的Chromium,避免重复下载。

方案3:使用Firebase层打包Chromium(多函数复用场景)

如果需要在多个Firebase Functions中使用相同版本的Chromium,可将其打包为Firebase层,避免每个函数重复携带浏览器文件:

  1. 下载与Puppeteer 19.3.8匹配的Chromium版本(可查看Puppeteer文档确认对应版本号)
  2. 按层目录结构放置Chromium:nodejs/node_modules/puppeteer/.local-chromium/[平台版本]/chrome-linux/chrome
  3. 部署层:
firebase deploy --only functions:layers:chromium-layer
  1. 在函数中引用层,并指定executablePath:
import puppeteer from 'puppeteer-core';
import * as functions from 'firebase-functions';
import { join } from 'path';

async function generatePDF(htmlContent: string): Promise<Buffer> {
  // 层中Chromium的路径,替换为实际版本号
  const executablePath = join(
    process.env.LAYER_PATH, 
    'nodejs/node_modules/puppeteer/.local-chromium/linux-1095492/chrome-linux/chrome'
  );
  
  const browser = await puppeteer.launch({
    headless: 'new',
    args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
    executablePath: executablePath,
  });

  // 后续逻辑同方案1
  functions.logger.log('browser.version()', await browser.version());
  const page = await browser.newPage();
  await page.setContent(htmlContent, { waitUntil: 'domcontentloaded' });
  const pdfBuffer = await page.pdf({ format: 'A4' });
  await browser.close();
  return pdfBuffer;
}

层可以被多个函数共享,有效降低单个函数的部署体积。

内容的提问来源于stack exchange,提问作者Fahry Mohammed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 17:52:49