Running Lighthouse in CircleCI

April 28, 2018

Update (October 2, 2018)

The code in this post uses lighthouse v2; it needs to be slightly modified to work with lighthouse v3. To skip straight to a working v3 example, visit the example repo I posted, which has been updated: https://github.com/zgreen/lighthouse-circleci-example.


Recently I set up Lighthouse to run in CircleCI. At the time, I wasn't able to find many resources online about how to do this, so I'm posting my work here.

Writing the Lighthouse tests

Create a file for your tests. I'm not running a ton of tests at the moment, so I run them all in a single file, lighthouse.test.js.

You'll need a pair of npm packages...

npm install --save-dev lighthouse chrome-launcher

And something to execute your tests. This example uses Jest:

npm install --save-dev jest
const lighthouse = require("lighthouse"); // Node CLI for Lighthouse https://www.npmjs.com/package/lighthouse#using-the-node-cli
const chromeLauncher = require("chrome-launcher"); // Launch Chrome from node

Jest sets a default timeout of 5 seconds for each test. Lighthouse can take longer to run, so you should increase that timeout if you're using Jest:

jest.setTimeout(60000); // Give it a minute, just in case.

Next, you'll need a helper function for launching Chrome and running Lighthouse, and returning the audits:

const launchChromeAndRunLighthouse = (
  url,
  opts = { chromeFlags: [] },
  config = null
) =>
  chromeLauncher.launch({ chromeFlags: opts.chromeFlags }).then(chrome => {
    opts.port = chrome.port;
    return lighthouse(url, opts, config).then(results =>
      chrome.kill().then(() => results)
    );
  });

Finally, write a test! This example tests whether the first meaningful paint score for https://example.com is greater than or equal to 50:

test("Meaningful first paint score", () =>
  launchChromeAndRunLighthouse(`https://example.com`).then(({ audits }) =>
    expect(audits["first-meaningful-paint"].score).toBeGreaterThanOrEqual(50)
  ));

Write as many of these as you want; Lighthouse returns a ton of useful data.

Add an npm test script

In package.json:

"scripts": {
  "test": "jest"
}

In this example, I'm running tests in Jest, so... that's all that's required.

Execute these tests in CircleCI

This example assumes the use of CircleCI 2.0.

Create a file, .circleci/config.yml:

# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2
jobs:
  build:
    docker:
      # specify the version you desire here
      - image: circleci/node:9.8.0-browsers
    working_directory: ~/repo
    steps:
      - checkout
      # Download and cache dependencies
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "package.json" }}
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-
      - run: yarn install
      - save_cache:
          paths:
            - node_modules
          key: v1-dependencies-{{ checksum "package.json" }}
      - run: yarn test

You can use the CircleCI CLI to run/test this out locally.

All done

That's it! Here's a repo with all of this put into action: https://github.com/zgreen/lighthouse-circleci-example

©2018 Zach Green