2

I want to use puppeteer on Lambda to convert HTML to PDF.
With the chrome-aws-lambda module or the puppeteer module, I'm trying to run (sam local invoke) a function that calls puppeteer.launch(), but the function returns an error.
If anyone is running puppeteer on Lambda, please let me know how you configured it!

CDK Stack

const pdfExportFunction = new lambda.NodejsFunction(this, 'ExportPDF', {
  runtime: Runtime.NODEJS_14_X,
  entry: 'lambda/export-pdf/index.ts',
  timeout: Duration.seconds(10),
  memorySize: 1024,
  // https://github.com/shelfio/chrome-aws-lambda-layer
  layers: [
    LayerVersion.fromLayerVersionArn(this, 'layer:chrome-aws-lambda', 'arn:aws:lambda:ap-northeast-1:764866452798:layer:chrome-aws-lambda:31')
  ]
})

Lambda Function Code (lambda/export-pdf/index.ts)

const chromium = require('@sparticuz/chrome-aws-lambda')

export const handler = async () => {
  try {
    const browser = await chromium.puppeteer.launch()
  } catch (error) {
    // Error: Cannot find module '/var/task/puppeteer/lib/Browser'
    console.log(error)
  }
}

I've tried several different ways to write imports, but each one gives me different errors when call puppeteer.launch().

// Error: Cannot find module '/var/task/puppeteer/lib/Browser'
const chromium = require('chrome-aws-lambda')
// Error: _projectRoot is undefined. Unable to create a BrowserFetcher.
const puppeteer = require('puppeteer')
// The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received undefined
import * as puppeteer from 'puppeteer'
kusumoto_teruya
  • 2,415
  • 4
  • 23
  • 38

1 Answers1

3

I went through the same errors you mentioned, here is how I succeeded.

First of all, I use a Docker container to run it. It was the easiest solution for me.

Dockerfile

FROM amazon/aws-lambda-nodejs:16

# Install Chrome to get all of the dependencies installed
ADD https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm chrome.rpm
RUN yum install -y ./chrome.rpm

COPY . ${LAMBDA_TASK_ROOT}/

RUN npm install
RUN npm run build-prod

# Handler of the lambda function (file out.js, function handler)
CMD [ "out.handler" ]

package.json

Note the build-prod script, I have excluded puppeteer from being bundled.

{
  "name": "test",
  "private": true,
  "version": "1.0.0",
  "source": "index.js",
  "scripts": {
    "build-prod": "esbuild index.js --bundle --platform=node --external:puppeteer --target=node16 --outfile=out.js"
  },
  "dependencies": {
    "puppeteer": "^15.4.0",
  },
  "devDependencies": {
    "esbuild": "^0.14.49"
  },
  "engines": {
    "node": ">= 16"
  }
}

index.js

import puppeteer from 'puppeteer';

export async function handler(event) {
    const browser = await puppeteer.launch({
        headless: true,
        executablePath: '/usr/bin/google-chrome',
        args: ['--no-sandbox', '--disable-setuid-sandbox', '--no-zygote'],
    })

    // Some stuff

    // Important!
    await browser.close()
}

Hoping this can help you!

Mathix420
  • 872
  • 11
  • 21
  • 1
    Thank you! The approach of deploying a Docker image with puppeteer installed to Lambda was very inspiring to me. However, since I am using an M1 Mac, perhaps I need to modify the Dockerfile above. I will look into it. – kusumoto_teruya Dec 02 '22 at 13:37
  • 1
    I changed the Dockerfile to install the packages needed to run puppeteer and it worked. Thanks! `RUN yum -y install libX11 libXcomposite libXcursor libXdamage libXext libXi libXtst cups-libs libXScrnSaver libXrandr alsa-lib pango atk at-spi2-atk gtk3` – kusumoto_teruya Dec 02 '22 at 16:19