Open7

wireit試してみた

ざっくりいうと、npm runの実行結果をキャッシュし、依存関係があるものに変更がなければ、実行をスキップして、キャッシュからアウトプットを引っ張り出して高速化しようぜというもの。

turborepoからキャッシュの機能だけ引っ張り出してきて、リモートキャッシュの概念はなくした感じ。
モノレポじゃなくても使える。(一応turborepoもモノレポじゃなくても使えるが)

もともとこんな感じで、package.json に定義されているscriptsを

  "scripts": {
    "build": "remix build",
    "test": "vitest run"
  }

こんな感じで書き換えると、wireitをプロキシしてスクリプトが実行される

  "scripts": {
    "build": "wireit",
    "test": "wireit"
  },
  "wireit": {
    "build": {
      "command": "remix build",
      "files": ["app", "server.js", "remix.config.js"],
      "output": ["build", "public/build"]
    },
    "test:": {
      "command": "vitest run",
      "files": ["app", "vitest.config.ts"],
    }
  }

filesが依存関係にあるファイルやディレクトリで、outputが生成されるもの。

https://github.com/google/wireit#configuration

初めてnpm run testを叩くと、こんな感じでこれまで通りスクリプトが実行される。
ランニングしている絵文字がキュート

$ npm run test

> test
> wireit

🏃 [test] Running command "vitest run"

 RUN  v0.9.4 /Users/xxxx/git/xxxxx

 √ app/sample.test.ts  (1 test) 2ms

Test Files  1 passed (1)
     Tests  1 passed (1)
      Time  879ms (in thread 2ms, 43948.50%)[test] Executed successfully

再度実行すると、一瞬でスクリプトが完走する。(ログだけではわかりにくいが)
✅ [test] Already freshと言われているときは、キャッシュから実行結果を引っ張ってきたということ

$ npm run test

> test:run
> wireit


 RUN  v0.9.4 /Users/xxxx/git/xxxx

 √ app/sample.test.ts  (1 test) 2ms

Test Files  1 passed (1)
     Tests  1 passed (1)
      Time  879ms (in thread 2ms, 43948.50%)[test] Already fresh

そして、依存関係に指定したファイルを変更して再度実行すると、最初の状態に戻り、キャッシュが再生成される。

使ってみて感じたメリット

  • npm run xxxのコマンド形式を変更しなくて良い
    • turborepoとかだと、turboコマンドを経由して実行しないといけない
      • ただ、基本的にはaliasにすると思うのであんまりメリット無いかも
  • 依存関係を明示しやすい
  • 個人的にはturborepoよりは始めやすい
    • 機能が絞られているので当たり前といえば当たり前

デメリット

  • npm runでしか動かないのでyarn runで実行するとエラーになる
    • 個人的にはワーニングくらいにして一応動くようにはしてほしい
  • 設定が冗長
    • package.jsonに書かないといけない
    • yarnを利用していると、"packageLocks": ["yarn.lock"]を何回も書かないといけない
    • 共通設定とかあったら便利なのになー
  • 依存関係の指定できるのはファイルとディレクトリだけ
    • turborepoだと特定の環境変数も依存対象に含むことができる
    • 環境変数に応じてビルドの結果を変えるみたいなケースでは使えない

仕組み

wireitを実行すると .wireitというディレクトリが生成される。
実行したコマンドごとに、下記のようなキャッシュキーとなるJSON型のファイルと、outputの結果をセットで保持している。

{"cacheable":true,"platform":"darwin","arch":"x64","nodeVersion":"v16.14.0","command":"vitest run","clean":true,"files":{"app/entry.client.tsx":"fb6dbb5b57e9f3681b47c7f3c15c26d5031e2fe39f1d7380e3a260c9e9012466","app/entry.server.tsx":"a771501c617a05db46365a590c5733f1a7afe6b6cb558bb37c4cdf1e7ce09446","app/root.tsx":"ebb67367000349d4ff42cc00c39bca51bb61b8f33c384acf4484eb1c5061a539","app/routes/index.tsx":"5e28bb7249eaecb547edd3babdf14445342bc683951016144c134e89b7caed71","app/routes/jokes.tsx":"b7ab6cc75b18b915d91b5e95514aca138aea9d3f8e719170093c4f8a4d4be968","app/sample.test.ts":"1154f01e25b37b330adad71e6b2e470efa6cccebed92150463d9f7279e8af6cc","app/styles/client.context.tsx":"b352661de4237bdaede7189a3840dc203a93526c79dd2b00431251c3bc5118a1","app/styles/createEmotionCache.ts":"71103150647e4ff40f3bb63b729d7425cfbef16736da5f0bfbeb8ca75bb2d295","app/styles/server.context.tsx":"2439f69228faee4b7def9cdfbb584d6f171fe56cc5b0aee6e18a72f26080c046","app/zod/customs/index.ts":"7992a39d6cde5e050eb78461a8bf9ad986175a94826e835c110b3967290bd249","app/zod/index.ts":"073590934bdb6e814b3fba301e200b360e4f8d8370c9071c9f68c8aefa2c3fb2","app/zod/user.ts":"a02f7a74954fc59161fb615c43e0794a7ff7f3a06a3a5c4ecbbf64135fcd56ba","node_modules/.prisma/client/index-browser.js":"7d2c554264306d7b0653449a6d675ddad7542e86fa340a37dc5de4039e3d5f03","node_modules/.prisma/client/index.d.ts":"c35e88f156530c49ec822db940601dc3ca013c3bc30b8bc938df46beffc0b2e6","node_modules/.prisma/client/index.js":"36c316f7233aa9ea5e93628954f38dba944e659e1489794d2338b75d413e0932","node_modules/.prisma/client/libquery_engine-darwin.dylib.node":"c0a90df2d127ef1d23f06f083bc8f37050a55f4ee517c559c8e4ef9997092273","node_modules/.prisma/client/package.json":"0fb742a452e6f213120576142c0517d102ed9bf4ba2e8803e764f9cf2dc3c3b4","node_modules/.prisma/client/schema.prisma":"b73c25e7990f2aede894bb405bac03d2a8563e82b31edd8bbbf6e490853e056f","vitest.config.ts":"1d153fc816bec69cccad5a7b5fde4aa68732bf007fd3099e801d248985834dfa","yarn.lock":"fd8fbf616d68e03503d158120e306b17f35894856cbe22d261801d81fb08d0ae"},"output":[],"dependencies":{}}

キャッシュのキーには、ファイル名とその中身をハッシュ化したデータが取られており、これが一致するかどうかでキャッシュを採用するか、洗い替えるかを判断しているっぽい。
この辺の仕組みは他の類似ライブラリも基本的にはだいたいそんな感じ。

READMEにはgithub actionsでのキャッシュの方法が記載されているが、.wireitディレクトリを保持できれば、他のgitlab-ciなどのCIでも高速化はできそう。

個人的には、

  • yarn runが使えなくなるのに抵抗がある
    • すべてのスクリプトにwireitを採用するわけではないので、どのコマンドがnpmで、どのコマンドがyarnなのかみたいなことを意識したくない
  • 環境変数も依存関係に指定したい

みたいな理由で採用自体は見送り。
ただし、turborepoよりも導入が楽だし気軽に使えるのはGood。
そして上に上げたような課題は今後のアップデートで改善されると思うので、ウォッチはし続けようと思う。

ログインするとコメントできます