Lighthouse CI 사용해보기 - 1

Lighthouse CI 사용해보기 - 1

기존에 사이트 성능을 측정할 때 매번 빌드 이후 사이트에 방문해서 페이지별로 lighthouse를 돌리는 작업을 진행했다.

매번 수작업으로 진행하던게 불편하던 차에 여유가 생겨 lighthouse-ci 를 통해 CI 과정에 넣어 보고자 한다.

Lighthouse CI 맛보기

우선 테스트를 위해 Vite를 통해 리액트 프로젝트를 생성한다.

yarn create vite lighthouse-ci-test --template react
cd lighthouse-ci-test

다음으로 Lighthouse CI (이하 lhci)를 위해 @lhci/cli 패키지가 필요하다.

이번엔 yarn dlx 를 사용해서 진행했다.

npm install -g @lhci/cli # 이렇게 전역 설치를 할 수도 있고
yarn dlx @lhci/cli # yarn v3 이상 사용시 이처럼 사용할 수도 있다.

다음으로 lhci 설정 파일인 .lighthouserc.cjs 를 만든다.

// .lighthouserc.cjs
module.exports = {
    ci: {
        collect: {
            startServerCommand: "yarn preview",
            url: ["http://127.0.0.1:4173"],
            numberOfRuns: 1,
            startServerReadyPattern: "Local",
            settings: {
                preset: "desktop",
            },
        },
        upload: {
            target: "temporary-public-storage",
        },
    },
};

이후 아래 명령으로 lhci 를 실행한다.

yarn build # 프로젝트 빌드
yarn dlx @lhci/cli autorun # 명령 실행

# 출력
➤ YN0000: ┌ Resolution step
➤ YN0061: │ intl-messageformat-parser@npm:1.8.1 is deprecated: We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser
➤ YN0061: │ raven@npm:2.6.4 is deprecated: Please upgrade to @sentry/node. See the migration guide https://bit.ly/3ybOlo7
➤ YN0061: │ uuid@npm:3.3.2 is deprecated: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
➤ YN0000: └ Completed in 3s 395ms
➤ YN0000: ┌ Fetch step
➤ YN0000: └ Completed
➤ YN0000: ┌ Link step
➤ YN0000: │ ESM support for PnP uses the experimental loader API and is therefore experimental
➤ YN0000: └ Completed in 0s 274ms
➤ YN0000: Done with warnings in 3s 818ms

✅  .lighthouseci/ directory writable
✅  Configuration file found
✅  Chrome installation found
⚠️   GitHub token not set
Healthcheck passed!

Started a web server with "yarn preview"...
Running Lighthouse 1 time(s) on http://127.0.0.1:4173
Run #1...done.
Done running Lighthouse!

Uploading median LHR of http://127.0.0.1:4173/...success!
Open the report at https://storage.googleapis.com/lighthouse-infrastructure.appspot.com/reports/~.report.html
No GitHub token set, skipping GitHub status check.

Done running autorun.

이후 아래 형태의 부분의 링크를 열어보면 측정 결과를 볼 수 있다.

Open the report at https://storage.googleapis.com/lighthouse-infrastructure.appspot.com/reports/~.report.html

Lighthouse CI 설정하기

위에서는 .lighthouserc.cjs 를 통해 설정 파일을 생성했다.

아래에서는 더 다양한 설정 파일에 몇 가지를 알아본다.

더 자세한 설명은 @lhci/configuration 에서 찾아볼 수 있다.

설정 파일 이름 정하기

lhci 에서 설정 파일은 아래 이름 중 하나만 만족하면 된다.

  1. .lighthouserc.js
  2. lighthouserc.js
  3. .lighthouserc.json
  4. lighthouserc.json
  5. .lighthouserc.yml
  6. lighthouserc.yml
  7. .lighthouserc.yaml
  8. lighthouserc.yaml

단 현재 프로젝트의 경우 .lighthouserc.js 로 파일을 생성할 경우, type: module 로 인해 아래의 오류를 만났다.

Error: require() of ES Module D:\Workspace\2211\lighthouse-ci-test\.lighthouserc.js from C:\Users\esllo\AppData\Local\Yarn\Berry\cache\@lhci-utils-npm-0.10.0-0c51ad16c2-8.zip\node_modules\@lhci\utils\src\lighthouserc.js not supported.
Instead change the require of .lighthouserc.js in C:\Users\esllo\AppData\Local\Yarn\Berry\cache\@lhci-utils-npm-0.10.0-0c51ad16c2-8.zip\node_modules\@lhci\utils\src\lighthouserc.js to a dynamic import() which is available in all CommonJS modules.

이를 해결하기 위해 두가지 방법을 사용할 수 있었다.

  • 확장자를 .cjs 로 변경하여 CommonJS 로 만들기
  • 파일에서 module.exports 를 제거하고 .json 파일로 만들기

기본 설정 형식

다양한 설정이 있지만 크게 아래 설정만 살펴본다.

더 자세한 설정은 @lhci/configuration 에서 확인할 수 있다.

module.exports = {
    ci: {
        collect: {
            url: [[...string]] // 실행할 url 배열
            staticDistDir: [string] // lhci가 테스트할 build 디렉토리
            startServerCommand: [string] // 스크립트 실행이 필요한 경우 staticDistDir 대신 실행 명령 사용
            startServerReadyPattern: [string: "listen|ready"] // 서버 실행 완료를 테스트하기 위한 정규식 패턴
            numberOfRuns: [number: 3] // 테스트를 실행할 횟수
            settings: {
                preset: "desktop" // 데스크톱 환경 테스트 여부, 생략시 기본값은 모바일 환경
            }
        },
        uplaod: {
            target: [string: 'lhci'] // 데이터를 업로드할 타겟  
        },
        assert: {},
        server: {},
        wizard: {},
    }
}

collect.url

실행할 url을 배열로 넣으며 위 테스트에서는 vite preview 실행 주소인 http://127.0.0.1:4173 으로 설정하였다.

여러 페이지를 테스트하고 싶으면 추가로 배열에 넣어주면 된다.

collect.staticDistDir

lhci 에서 테스트할 빌드 디렉토리를 지정하며, lhci 가 측정하는 동안 자체적으로 서버를 열어 테스트한다.

정적으로 된 프로젝트를 테스트할 때 사용하며, url 오리진이 localhost 가 아니거나, startServerCommand 와 함께 사용할 수 없다.

collect.startServerCommand

lhci 에서 테스트할 빌드가 스크립트로 실행이 가능한 경우 사용한다. 웹서버를 직접 실행해야 하는 경우 유용하다.

역시 staticDistDir 과 함께 사용할 수 없다.

collect.startServerReadyPattern

서버가 실행이 완료되었을 때 문자열을 확인할 수 있는 정규식 패턴을 지정한다.

위에서는 vite preview 를 통해 서버를 실행했고, 실행시 출력 결과는 아래와 같다.

yarn preview
# 출력
  ➜  Local:   http://127.0.0.1:4173/
  ➜  Network: use --host to expose

위에서 종료 여부를 체크하기 위해 Local 이라는 문자열을 넣어 실행 완료를 체크하도록 했다.

collect.numberOfRuns

측정을 몇 번 실행할지 지정한다. 기본값은 3회이며 권장은 5회라고 한다.

collect.settings.preset

실행 환경을 지정한다. 기본은 모바일 환경이며 desktop 을 통해 데스크톱 환경을 테스트할 수 있다.

upload.target

실행 결과를 어디에 저장할지 지정한다. 기본값은 lhci 이며 이외에 temporary-public-storagefilesystem 이 있다.

  • lhci : Lighthouse CI Server 에 저장한다.
    • 오랜 기간 저장할 수 있다.
    • 결과에 대한 접근을 제한할 수 있다.
  • temporary-public-storage : GCP Cloud 에 저장된다.
    • 저장이 되면 며칠 후 삭제된다.
    • 추가 비용 없이 링크를 통해 아무나 접근할 수 있다.
  • filesystem : Local 시스템에 저장한다.
    • 내 시스템에 직접 저장하여 직접 제어할 수 있다.

Written by@[esllo]
plain developer

GitHubTwitterLinkedIn