Madogiwa Blog

主に技術系の学習メモに使っていきます。

Lighthouse CIとCircleCI ArtifactsでRailsアプリケーションのLighthouseのスコアを計測するMEMO

フロントエンドまわりの改善の指標としてLighthouseを使ってパフォーマンス等のスコアを参考にすることがあるかと思うのですが、 なかなかchromeで開いて手動で測定するのは手間だったのでCircle CIで実行して結果をArtifactsで確認できるようしたら結構良かったのでメモしておきます📝

計測した環境はrails 6.0.3.2です🚃

Lighthouse CIでcliでLighthouseを実行できるようにする

まずはLighthouseをcliで実行できるように@lhci/cliをinstallします。

github.com

yarn add -D @lhci/cli@0.4.x

※公式ドキュメントはnpm install -g @lhci/cli@0.4.xをCircleCIのstepで実行するような形になっていましたが開発環境でも見れると便利そうだったのでpackage.jsonで管理するようにしてみました。

その後はプロジェクトのルートにlighthouserc.jsを配置します。

/* 
NOTE: 
- collect
  * settingsは一旦capybara側の設定と合わせた
  * startServerCommandは既存の開発用のportと競合しないように3001で起動
- uploard
  * targetはデフォルトだと`lhci`で結果格納用の環境が必要なのでfilesystemでlocalに保存するようにした
  * outputDirはgitignoreで指定できるおうに固定のディレクトリにした
詳細はこちら: [https://github.com/GoogleChrome/lighthouse-ci/blob/v0.4.4/docs/configuration.md:title]
*/
module.exports = {
  ci: {
    collect: {
      url: ["http://localhost:3001"],
      startServerCommand: `bin/rails s -p 3001`,
      startServerReadyPattern: "Puma starting",
      settings: {chromeFlags: 'headless --disable-gpu --no-sandbox --disable-dev-shm-usage'},
      numberOfRuns: 3
    },
    upload: {
      target: 'filesystem',
      outputDir: './.lighthouseci_result'
    },
  },
};

下記のような形でスクリプトを定義してyarn run lighthorseで実行できるようにしときます。

  "scripts": {
    "lighthorse": "lhci autorun",

これでCLIでlighthouseを実行して結果を確認できるようになりました🎉 .lighthouseci_result/配下のhtmlファイルをブラウザで開くといい感じに確認出来ます✨

$ yarn run lighthorse
yarn run v1.19.2
$ lhci autorun
✅  .lighthouseci/ directory writable
✅  Configuration file found
✅  Chrome installation found
Healthcheck passed!

Started a web server with "bin/rails s -p 3001"...
Running Lighthouse 3 time(s) on http://localhost:3001
Run #1...done.
Run #2...done.
Run #3...done.
Done running Lighthouse!

Dumping 3 reports to disk at /dogfeeds/.lighthouseci_result...
Done writing reports to disk.

Done running autorun.
Done in 48.15s.

$ ls .lighthouseci_result/
localhost-_-2020_08_06_05_59_35.report.html  localhost-_-2020_08_06_05_59_49.report.html  localhost-_-2020_08_06_06_00_03.report.html  manifest.json
localhost-_-2020_08_06_05_59_35.report.json  localhost-_-2020_08_06_05_59_49.report.json  localhost-_-2020_08_06_06_00_03.report.json

CircleCIでLighthouseを実行してArtifactsで結果を確認できるようにする

あとはCircleCIでyarn run lighthouseを実行して.lighthouseci_resultに保存された結果をArtifactsとしてCIの結果画面から確認できるようにします👍

Artifactsの使い方は過去に記事にしてるので、そちらを確認してみてください。

madogiwa0124.hatenablog.com

ポイントは、本番環境と合わせるために下記のような形でcommandsでparametersを定義してNODE_ENVの値を渡せるようにしてあげて、lighthouseの計測前にrails webpacker:compileを本番用のビルドを実行するようにしてあげるようにしました。

commands:
  build_webpack:
    parameters:
      env:
        type: string
        default: test
    steps:
      - run:
          name: build webpack
          command: NODE_ENV=<<parameters.env>> bundle exec rails webpacker:compile

全体のCircleCIの設定ファイルは下記のような感じです。

version: 2.1

web: &web
  - image: circleci/ruby:2.7.0-node-browsers
    environment:
      RAILS_ENV: test
      PGHOST: 127.0.0.1
      DATABASE_USER: circleci
      DATABASE_PASSWORD: password
db: &db
  - image: circleci/postgres
    environment:
      POSTGRES_USER: circleci
      POSTGRES_PASSWORD: password

executors:
  web:
    docker:
      - <<: *web
  web-db:
    docker:
      - <<: *web
      - <<: *db

commands:
  attach_current:
    steps:
      - attach_workspace:
          at: .
  install_node_deps:
    steps:
      - run:
          name: install node dependencies
          command: yarn install
  cache_node_deps:
    steps:
      - save_cache:
          name: Cache node dependencies
          paths:
            - ./node_modules
          key: v1-node-dependencies-{{ checksum "yarn.lock" }}
  restore_node_deps:
    steps:
      - restore_cache:
          name: Restore node dependencies
          keys:
            - v1-node-dependencies-{{ checksum "yarn.lock" }}
            - v1-dependencies-
  configure_bundler:
    steps:
      - run:
          name: Configure Bundler
          command: |
            echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
            source $BASH_ENV
            gem install bundler -v $BUNDLER_VERSION
  install_ruby_deps:
    steps:
      - run:
          name: install dependencies
          command: bundle install --jobs=4 --clean --path ./vendor/bundle
  cache_ruby_deps:
    steps:
      - save_cache:
          name: Cache ruby dependencies
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}
  restore_ruby_deps:
    steps:
      - restore_cache:
          name: Restore ruby dependencies
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-
  rails_migration:
    steps:
      - run:
          name: run migration
          command: |
            bundle exec rake db:create
            bundle exec rake db:schema:load
  build_webpack:
    parameters:
      env:
        type: string
        default: test
    steps:
      - run:
          name: build webpack
          command: NODE_ENV=<<parameters.env>> bundle exec rails webpacker:compile
  store_lighthorse_atifacts:
    steps:
      - store_artifacts:
          path: .lighthouseci_result
jobs:
  build:
    executor:
      name: web
    steps:
      - checkout
      - persist_to_workspace:
          root: .
          paths:
            - .
  node_build:
    executor:
      name: web
    steps:
      - attach_current
      - restore_node_deps
      - install_node_deps
      - cache_node_deps
  ruby_build:
    executor:
      name: web
    steps:
      - attach_current
      - configure_bundler
      - restore_ruby_deps
      - install_ruby_deps
      - cache_ruby_deps
  lighthourse:
    executor:
      name: web-db
    steps:
      - attach_current
      - restore_ruby_deps
      - restore_node_deps
      - configure_bundler
      - install_ruby_deps
      - install_node_deps
      - rails_migration
      # 本番と同様のbuildでlighthouseのチェックを行うためpruductionでビルド
      - build_webpack:
          env: production
      - run:
          name: lighthourse
          command: yarn run lighthorse
      - store_lighthorse_atifacts
workflows:
  version: 2
  build:
    jobs:
      - build
      - ruby_build:
          requires:
            - build
      - node_build:
          requires:
            - build
      - lighthourse:
          requires:
            - ruby_build
            - node_build

おわりに

個人のサービスで計測できるようにしたのですが、下記のように結構改善しました✨

before

f:id:madogiwa0124:20200806150902p:plain

after

f:id:madogiwa0124:20200806150926p:plain

やはり定量的に定期的に計測できるようにすると改善のモチベーションが上がっていきますね💪

参考資料

github.com