`bin/dev` でRailsサーバーとJSウォッチャーを一括起動

basecamp/lexxy

foremanbin/dev スクリプトを導入することで、ローカル開発時に必要な複数プロセスを1コマンドで起動できるようになりました。これにより、従来は別々のターミナルで実行していた2つのプロセスを統一されたエントリポイントに集約しています。

背景

これまでのローカル開発では、RailsサーバーとJSウォッチャーを別々のコマンドで起動する必要がありました。具体的には、bin/rails serveryarn build -w をそれぞれ別のターミナルセッションで実行する必要があり、開発環境のセットアップ手順が複数のステップに分散していました。

さらに、Railsサーバーの起動時に前回のプロセスが残存していると、tmp/pids/server.pid が残ったまま起動に失敗するケースがありました。このような「stale PID」の問題も開発体験を損なう要因となっていました。

これらの課題を解消するため、プロセス管理ツールの foreman と統一エントリポイントとなる bin/dev が導入されました。

技術的な変更

今回の変更は、Procfile.devbin/devGemfile の3つのファイルの追加・修正で構成されています。

Procfile.dev は、foremanが起動するプロセスを定義するファイルです。

web: bin/rails server
js: yarn watch

web プロセスでRailsサーバーを、js プロセスでJSウォッチャーをそれぞれ管理します。foremanはこれらのプロセスの標準出力をプレフィックス付きで多重化して表示し、どちらかが異常終了した場合はもう一方も停止します。

bin/dev は、stale PIDの処理とforemanの起動を担うBashスクリプトです。

#!/usr/bin/env bash

# Kill any previous Rails server
if [ -f tmp/pids/server.pid ]; then
  pid=$(cat tmp/pids/server.pid)
  if kill -0 "$pid" 2>/dev/null; then
    echo "Killing previous Rails server (PID: $pid)..."
    kill "$pid"
    wait "$pid" 2>/dev/null
  fi
  rm -f tmp/pids/server.pid
fi

exec foreman start -f Procfile.dev -p 3000 "$@"

PIDファイルが存在する場合、kill -0 でプロセスの生存確認を行い、実際に動作中の場合のみ kill でプロセスを終了します。PIDファイルが残っているがプロセスが既に存在しない場合は、kill -0 が失敗するためスキップされ、PIDファイルのみ削除されます。最後の exec foreman start により、スクリプト自身のプロセスをforemanに置き換えることでプロセス管理を簡潔にしています。"$@" を渡すことで、bin/dev に渡した追加オプションをそのままforemanに転送できます。

Gemfile への foreman の追加は最小限の変更です。

gem "foreman"

開発専用の group :development ブロックではなく、トップレベルに追加されています。

設計判断

bin/dev によるstale PIDの事前クリーンアップを、foreman起動の前処理として組み込む構成が採用されました。

foremanはプロセスの起動と管理を担いますが、前回のRailsサーバープロセスが残留している場合の処理は担いません。bin/dev にこのクリーンアップロジックを持たせることで、開発者が毎回手動でPIDファイルを確認・削除する手間を排除しています。kill -0 によるプロセス生存確認を挟むことで、PIDファイルは残っているがプロセスは既に終了済みという状況でも安全に動作します。

また、exec によるプロセス置き換えを使っている点も注目です。bash bin/dev がforemanの親プロセスとして残るのではなく、foremanがシェルのプロセスを引き継ぐため、シグナルのハンドリングがシンプルになります。

まとめ

foremanbin/dev の導入により、ローカル開発のエントリポイントが bin/dev の1コマンドに集約されました。stale PIDのクリーンアップとプロセスの多重起動を組み合わせることで、Railsアプリケーションでよく見られる開発環境の煩雑さを解消するシンプルかつ堅牢な設計となっています。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
c6e64afe

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

記事構成は「総論→各論→結論」の3部構成に準拠しており、リード文、背景、技術的な変更、設計判断、まとめの各要素が明確に配置されています。特に、任意要素である「設計判断」セクションを設けることで、変更の意図が深く解説されており秀逸です。

カスタムMarkdown構文 ⚠ WARNING

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライトは正しく使用されています。しかし、GitHubのPRリンク記法がガイドラインの推奨形式(`[#817](URL)`)ではなく、`[PR #817](URL)`となっています。内容理解に支障はありませんが、ガイドラインとの不一致が見られます。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

Rails開発における一般的な課題(複数プロセスの管理、stale PID)を題材に、`foreman`や`bin/dev`といった具体的なツールやスクリプトを解説しており、専門知識を持つエンジニアという対象読者に完全に適合しています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論の構成で書かれ、各段落はトピックセンテンスで始まっています。1段落1トピックが守られ、段落長も適切です。非常に読みやすく、構造的な文章です。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

`Procfile.dev`、`bin/dev`、`Gemfile`に関するコード引用は、提供されたDiff情報と完全に一致しています。ファイル名も正確であり、コードの省略や改変はありません。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`foreman`、`stale PID`、`kill -0`、`exec`といった技術用語が文脈に応じて正確に使用されており、それぞれの機能に関する説明も的確です。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

`bin/dev`スクリプトによるstale PIDのクリーンアップ処理や、`exec`によるプロセス置き換えの解説など、技術的な説明はすべてDiffの内容と論理的に整合性が取れています。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張は、PRのタイトル、Description、Diffの内容によって裏付けられています。旧来の開発手順(`yarn build -w`)に関する記述も、`docs/development.md`のDiffから正確に読み取っており、ハルシネーションは認められません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#817)やポート番号(3000)など、記事内に含まれる数値や固有名詞はすべて正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「`bin/dev` でRailsサーバーとJSウォッチャーを一括起動」は、PRの主題「Add foreman with bin/dev for local development」をユーザーの利益視点で的確に要約しており、内容との整合性も取れています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事はPR情報に忠実であり、バージョン情報やリリース予定など、PRに記載のない外部知識を持ち込んでいません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

「これまでの〜」といった表現で過去の状況を説明し、変更によって「〜できるようになった」と現在形・完了形で記述しており、時間表現は正確です。