From 9c5422fc15a17a2839a4c3ee27337406bc7d298e Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Tue, 4 Nov 2025 17:04:30 -1000 Subject: [PATCH] Improve pack generation to avoid unnecessary subprocess spawning Refactors pack_generator.rb to intelligently choose between direct Rake task execution and bundle exec based on the current context. When running in a Rails/Bundler environment (e.g., from bin/dev), the pack generation now runs the Rake task directly, avoiding the overhead of spawning a subprocess. Key improvements: - Adds run_pack_generation method that detects Rails availability - Implements run_rake_task_directly for in-process execution when Rails is available - Falls back to run_via_bundle_exec when Rails is not available - Includes proper silent mode handling for both execution paths - Prevents dead code by ensuring Rails is always defined before use This change is based on the optimization from the shakapacker-9.3.0 branch (commit b716f081), which already excluded the dead code that would have checked for Rails being defined when it's guaranteed to be present. Fixes #1909 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude --- lib/react_on_rails/dev/pack_generator.rb | 61 +++++++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/lib/react_on_rails/dev/pack_generator.rb b/lib/react_on_rails/dev/pack_generator.rb index 9e74bf0631..336b72838a 100644 --- a/lib/react_on_rails/dev/pack_generator.rb +++ b/lib/react_on_rails/dev/pack_generator.rb @@ -9,10 +9,10 @@ class << self def generate(verbose: false) if verbose puts "📦 Generating React on Rails packs..." - success = system "bundle exec rake react_on_rails:generate_packs" + success = run_pack_generation else print "📦 Generating packs... " - success = system "bundle exec rake react_on_rails:generate_packs > /dev/null 2>&1" + success = run_pack_generation(silent: true) puts success ? "✅" : "❌" end @@ -21,6 +21,63 @@ def generate(verbose: false) puts "❌ Pack generation failed" exit 1 end + + private + + def run_pack_generation(silent: false) + # If we're already inside a Bundler context AND Rails is available (e.g., called from bin/dev), + # we can directly require and run the task. Otherwise, use bundle exec. + if defined?(Bundler) && rails_available? + run_rake_task_directly(silent: silent) + else + run_via_bundle_exec(silent: silent) + end + end + + def rails_available? + return false unless defined?(Rails) + return false unless Rails.respond_to?(:application) + return false if Rails.application.nil? + + true + end + + def run_rake_task_directly(silent: false) + require "rake" + + # Load tasks only if not already loaded (don't clear all tasks) + Rails.application.load_tasks unless Rake::Task.task_defined?("react_on_rails:generate_packs") + + if silent + original_stdout = $stdout + original_stderr = $stderr + $stdout = StringIO.new + $stderr = StringIO.new + end + + begin + task = Rake::Task["react_on_rails:generate_packs"] + task.reenable # Allow re-execution if called multiple times + task.invoke + true + rescue StandardError => e + warn "Error generating packs: #{e.message}" unless silent + false + ensure + if silent + $stdout = original_stdout + $stderr = original_stderr + end + end + end + + def run_via_bundle_exec(silent: false) + if silent + system "bundle exec rake react_on_rails:generate_packs > /dev/null 2>&1" + else + system "bundle exec rake react_on_rails:generate_packs" + end + end end end end