Lighthouse: Running lighthouse inside a serverless function

Created on 3 Aug 2020  路  4Comments  路  Source: GoogleChrome/lighthouse

I am using vercel serverless function and I would like to know if there is any guide on how to run lighthouse inside a serverless function? On localhost it works fine but when I deploy my app it returns an error when hitting the endpoint:

This is my code:

const lighthouse = require("lighthouse");
const chromeLauncher = require("chrome-launcher");
const { generateLighthouseStats } = require("../src/generateLighthouseStats");
module.exports = async (req, res) => {
  let { website } = req.query;

  const categories = "performance,seo,accessibility,pwa,best-practices";

  const categoriesList = categories.split(",").filter(Boolean);

  const chrome = await chromeLauncher.launch({
    chromeFlags: ["--headless"]
  });

  const options = {
    logLevel: "info",
    onlyCategories: categoriesList,
    port: chrome.port
  };

  const runnerResult = await lighthouse(website, options);
  const response = {};
  if (categoriesList.includes("performance")) {
    const performance = runnerResult.lhr.categories.performance.score * 100;
    response.performance = performance;
  }
  if (categoriesList.includes("seo")) {
    const seo = runnerResult.lhr.categories.seo.score * 100;
    response.seo = seo;
  }
  if (categoriesList.includes("accessibility")) {
    const accessibility = runnerResult.lhr.categories.accessibility.score * 100;
    response.accessibility = accessibility;
  }
  if (categoriesList.includes("pwa")) {
    const pwa = runnerResult.lhr.categories.pwa.score * 100;
    response.pwa = pwa;
  }
  if (categoriesList.includes("best-practices")) {
    const bestPractices = runnerResult.lhr.categories["best-practices"].score * 100;
    response.bestPractices = bestPractices;
  }

  await chrome.kill();

  res.setHeader("Content-Type", "image/svg+xml");
  res.setHeader("Cache-Control", `public, max-age=1600`);
  res.send(
    generateLighthouseStats(
      {
        performance: response.performance,
        accessibility: response.accessibility,
        seo: response.seo,
        pwa: response.pwa,
        bestPractices: response.bestPractices
      },
      runnerResult.lhr.finalUrl
    )
  );
};

2020-08-03T11:01:28.936Z    6334e987-a67a-4c9e-9061-3cf3a7f79318    ERROR   Unhandled Promise Rejection     {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"Error: The environment variable CHROME_PATH must be set to executable of a build of Chromium version 54.0 or later.","reason":{"errorType":"Error","errorMessage":"The environment variable CHROME_PATH must be set to executable of a build of Chromium version 54.0 or later.","code":"ERR_LAUNCHER_PATH_NOT_SET","message":"The environment variable CHROME_PATH must be set to executable of a build of Chromium version 54.0 or later.","stack":["Error: ","    at new LauncherError (/var/task/node_modules/chrome-launcher/src/utils.ts:31:18)","    at new ChromePathNotSetError (/var/task/node_modules/chrome-launcher/dist/utils.js:44:9)","    at Object.linux (/var/task/node_modules/chrome-launcher/src/chrome-finder.ts:153:11)","    at Function.getFirstInstallation (/var/task/node_modules/chrome-launcher/src/chrome-launcher.ts:183:61)","    at Launcher.<anonymous> (/var/task/node_modules/chrome-launcher/src/chrome-launcher.ts:229:37)","    at Generator.next (<anonymous>)","    at /var/task/node_modules/chrome-launcher/dist/chrome-launcher.js:13:71","    at new Promise (<anonymous>)","    at __awaiter (/var/task/node_modules/chrome-launcher/dist/chrome-launcher.js:9:12)","    at Launcher.launch (/var/task/node_modules/chrome-launcher/dist/chrome-launcher.js:156:16)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: Error: The environment variable CHROME_PATH must be set to executable of a build of Chromium version 54.0 or later.","    at process.<anonymous> (/var/runtime/index.js:35:15)","    at process.emit (events.js:322:22)","    at process.emit (/var/task/__sourcemap_support.js:2561:21)","    at processPromiseRejections (internal/process/promises.js:209:33)","    at processTicksAndRejections (internal/process/task_queues.js:98:32)"]}
Unknown application error occurred
needs-priority pending-close question

All 4 comments

Lighthouse needs Chrome on the machine. I'd be surprised if vercel serverless made Chrome available. Even if you bundled chromium like some solutions out there for lambda, we'd definitely recommend against it for any performance results.

@patrickhulce Yes I figured this out since it needs more than 124mb of storage. Probably serverless is not a good use for this kind of work. Thank you !! What would you recommend to carry this type of work? I was actually trying to create an api where you feed it the website and it returns an image with all the metrics from lighthouse.

The link to documentation above also has what hardware we do recommend 馃槈

AWS's m5.large, GCP's n2-standard-2, and Azure's D2 all should be sufficient to run a single Lighthouse run at a time (~$0.10/hour for these instance types, ~30s/test, ~$0.0008/Lighthouse report).

Thank you @patrickhulce for your help !!

Was this page helpful?
0 / 5 - 0 ratings