Running Lighthouse in CircleCI

April 28, 2018

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