Madogiwa Blog

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

eslint/stylelintの実行結果をcacheして実行時間を削減するメモ

eslint、stylelintにもcache用のオプションがあって差分のあったファイルだけ実行して時間を削減できることを知らなかったのでやり方とかをmemo🗒

eslintでcacheを利用する

TL;DR

eslint --cache --cache-location node_modules/.cache/eslint/ --cache-strategy content

eslintでcacheを利用するには、基本的には以下のoptionを実行時に付与するだけです。

--cache
Store the info about processed files in order to only operate on the changed ones. The cache is stored in .eslintcache by default. Enabling this option can dramatically improve ESLint’s running time by ensuring that only changed files are linted.
https://eslint.org/docs/latest/user-guide/command-line-interface#--cache-location

デフォルトだとプロジェクトのrootにキャッシュ用のファイルが作成されます。.gitignoreのメンテがめんどくさかったのとrootに色々できるのが嫌だったので、--cache-locationを指定してnode_modules/.cache/eslint配下に作成するようにしました。

--cache-location
Path to the cache location. Can be a file or a directory. If no location is specified, .eslintcache will be used. In that case, the file will be created in the directory where the eslint command is executed.
https://eslint.org/docs/latest/user-guide/command-line-interface#--cache-location

またデフォルトのmetadataベースでのchaceではCIではcheckoutして実行する都合上、上手く動かないので--cache-strategy contentを指定してcontentベースでのcacheを利用するようにしました。

--cache-strategy
Strategy for the cache to use for detecting changed files. Can be either metadata or content. If no strategy is specified, metadata will be used. The content strategy can be useful in cases where the modification time of your files change even if their contents have not. For example, this can happen during git operations like git clone because git does not track file modification time.
https://eslint.org/docs/latest/user-guide/command-line-interface#--cache-strategy

実行時間を約1/10に出来ました✨

// キャッシュなし
$ eslint app/javascript spec/javascript --ext .vue,.js,.ts --cache --cache-strategy content --cache-location node_modules/.cache/eslint/
Done in 14.40s.

// キャッシュあり
$ eslint app/javascript spec/javascript --ext .vue,.js,.ts --cache --cache-strategy content --cache-location node_modules/.cache/eslint/
Done in 1.16s.

CIでeslintのcacheを利用する

- name: cache eslint
        uses: actions/cache@v3
        with:
          path: node_modules/.cache/eslint
          key: eslint-v1-${{ github.ref_name }}-${{ github.sha }}
          restore-keys: |
            eslint-v1-
      - name: lint js
        run: yarn run eslint app/javascript spec/javascript --ext .vue,.js,.ts --cache --cache-strategy content --cache-location node_modules/.cache/eslint/

eslintのバージョンアップ等の際にファイルの差分がなくても実行したいケースとかもあるかもなので、cacheのkeyをeslint-v1-${{ hashFiles('**/yarn.lock') }}-${{ github.ref_name }}-${{ github.sha }}とかにしておいてrestore-keyseslint-v1-${{ hashFiles('**/yarn.lock') }}-にしておいても良いかも?※yarn.lockが一致してない場合にはcacheを利用しない。

https://docs.github.com/ja/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key

stylelintでcacheを利用する

TL;DR

stylelint --cache --cache-location node_modules/.cache/stylelint/

stylelintでもcacheを利用するには、基本的には以下のoptionを実行時に付与するだけです。

CLI flag: --cache
Store the results of processed files so that Stylelint only operates on the changed ones. By default, the cache is stored in ./.stylelintcache in process.cwd().
Options | Stylelint

デフォルトだとプロジェクトのrootにキャッシュ用のファイルが作成されます。同様に.gitignoreのメンテがめんどくさかったのとrootに色々できるのが嫌だったので、--cache-locationを指定してnode_modules/.cache/stylelint配下に作成するようにしました。

CLI flag: --cache-location
Path to a file or directory for the cache location.
https://stylelint.io/user-guide/usage/options/#cachelocation

私の環境では実行時間が約1/2ぐらいになりました✨

CIでstylelintのcacheを利用する

styelintではmetadataベースのcacheしかサポートされておらずCIで実行時間を削減することはできません😭

issueは上がっているようなので、今後はできるようになるかもしれません。

github.com

(10/16追記) Stylelint v14.13.0でcacheStorategyが追加されcontentベースのcacheが利用できるようになりました🙌

github.com

おわりに

意外と静的解析系のライブラリこういうオプション指定するだけ系で実行時間が大分変わりそうなので、指定できるものは指定しておくと効率が上がってよさそうですね🗒