PM2 とは
PM2 is a daemon process manager
P
rocessM
anager
理由
- メジャーな OSS であり、信頼でき、メンテも続くだろう
- Webサーバ の起動、停止、削除というだけに限らず、汎用的なので、応用範囲が広い
- 同期的な処理にできるので、サーバが起動しない前にテストが走って落ちてしまうということがない
- Cypress 公式では start-server-and-test が紹介されていたり、Vue Test Utils でもなにか紹介されていた*1と思うが、これらは非同期でサーバを起動する*2ので、サーバ起動よりも早くテストが実行されることがある
- ローカルの超早マシンだと落ち、CI だと通る、みたいな Flaky な悩みどころを生んでしまい、体験的に良くない
- Cypress 公式では start-server-and-test が紹介されていたり、Vue Test Utils でもなにか紹介されていた*1と思うが、これらは非同期でサーバを起動する*2ので、サーバ起動よりも早くテストが実行されることがある
ローカルでも CI でも同じコマンド(の流れ)で使える
- CI だとサーバ起動しっぱなしでもいいが、ローカルだと起動したままテストが落ちる場合なども考慮する必要がある
- pm2 なら自分で命名した名前に対して冪等に kill できるので、ローカルでも CI でも同じコマンドで
"scripts"
に定義できる
- pm2 なら自分で命名した名前に対して冪等に kill できるので、ローカルでも CI でも同じコマンドで
- CI だとサーバ起動しっぱなしでもいいが、ローカルだと起動したままテストが落ちる場合なども考慮する必要がある
SSG ならば http-server を Webサーバ として用い、PM2 で管理するといい
具体例
Next.js で SSG を採用する場合の E2Eテスト を Cypress で行う場合、次のようにして ローカル実行 と CI (GitHub Actions) での実行で共通化できています*3。
{ "scripts": { "test:e2e": "npx --yes pm2 delete my_product_e2e_test 2> /dev/null & yarn build && npx pm2 start 'npx --yes http-server out/ -p 3000' --name my_product_e2e_test && yarn cypress:run && npx --yes pm2 delete my_product_e2e_test", } }
最初にも $ pm2 delete
している理由は、ローカルのテスト実行で落ちたときにサーバが起動しっぱなしになっていることを考慮しているからです。最初に $ pm2 delete
するように書いておけば冪等にできます。
なお、もしサーバが起動していないにも関わらず $ pm2 delete
するとエラーになる*4 ので、その対策として 2> /dev/null
したり、コマンドの連結を &
で行ったりしています。