@@ -8,10 +8,10 @@ module ReactOnRails
88 module Dev
99 class ServerManager
1010 class << self
11- def start ( mode = :development , procfile = nil , verbose : false , route : nil )
11+ def start ( mode = :development , procfile = nil , verbose : false , route : nil , rails_env : nil )
1212 case mode
1313 when :production_like
14- run_production_like ( _verbose : verbose , route : route )
14+ run_production_like ( _verbose : verbose , route : route , rails_env : rails_env )
1515 when :static
1616 procfile ||= "Procfile.dev-static-assets"
1717 run_static_development ( procfile , verbose : verbose , route : route )
@@ -119,7 +119,7 @@ def show_help
119119 def run_from_command_line ( args = ARGV )
120120 require "optparse"
121121
122- options = { route : nil }
122+ options = { route : nil , rails_env : nil }
123123
124124 OptionParser . new do |opts |
125125 opts . banner = "Usage: dev [command] [options]"
@@ -128,6 +128,10 @@ def run_from_command_line(args = ARGV)
128128 options [ :route ] = route
129129 end
130130
131+ opts . on ( "--rails-env ENV" , "Override RAILS_ENV for assets:precompile step only (prod mode only)" ) do |env |
132+ options [ :rails_env ] = env
133+ end
134+
131135 opts . on ( "-h" , "--help" , "Prints this help" ) do
132136 show_help
133137 exit
@@ -140,7 +144,7 @@ def run_from_command_line(args = ARGV)
140144 # Main execution
141145 case command
142146 when "production-assets" , "prod"
143- start ( :production_like , nil , verbose : false , route : options [ :route ] )
147+ start ( :production_like , nil , verbose : false , route : options [ :route ] , rails_env : options [ :rails_env ] )
144148 when "static"
145149 start ( :static , "Procfile.dev-static-assets" , verbose : false , route : options [ :route ] )
146150 when "kill"
@@ -182,12 +186,21 @@ def help_commands
182186 end
183187 # rubocop:enable Metrics/AbcSize
184188
189+ # rubocop:disable Metrics/AbcSize
185190 def help_options
186191 <<~OPTIONS
187192 #{ Rainbow ( '⚙️ OPTIONS:' ) . cyan . bold }
188- #{ Rainbow ( '--verbose, -v' ) . green . bold } #{ Rainbow ( 'Enable verbose output for pack generation' ) . white }
193+ #{ Rainbow ( '--route ROUTE' ) . green . bold } #{ Rainbow ( 'Specify route to display in URLs (default: root)' ) . white }
194+ #{ Rainbow ( '--rails-env ENV' ) . green . bold } #{ Rainbow ( 'Override RAILS_ENV for assets:precompile step only (prod mode only)' ) . white }
195+ #{ Rainbow ( '--verbose, -v' ) . green . bold } #{ Rainbow ( 'Enable verbose output for pack generation' ) . white }
196+
197+ #{ Rainbow ( '📝 EXAMPLES:' ) . cyan . bold }
198+ #{ Rainbow ( 'bin/dev prod' ) . green . bold } #{ Rainbow ( '# NODE_ENV=production, RAILS_ENV=development' ) . white }
199+ #{ Rainbow ( 'bin/dev prod --rails-env=production' ) . green . bold } #{ Rainbow ( '# NODE_ENV=production, RAILS_ENV=production' ) . white }
200+ #{ Rainbow ( 'bin/dev prod --route=dashboard' ) . green . bold } #{ Rainbow ( '# Custom route in URLs' ) . white }
189201 OPTIONS
190202 end
203+ # rubocop:enable Metrics/AbcSize
191204
192205 def help_customization
193206 <<~CUSTOMIZATION
@@ -225,17 +238,19 @@ def help_mode_details
225238
226239 #{ Rainbow ( '🏭 Production-assets mode' ) . cyan . bold } - #{ Rainbow ( 'Procfile.dev-prod-assets' ) . green } :
227240 #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'React on Rails pack generation before Procfile start' ) . white }
228- #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Asset precompilation with production optimizations' ) . white }
229- #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Optimized, minified bundles' ) . white }
230- #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Extracted CSS files (no FOUC)' ) . white }
241+ #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Asset precompilation with NODE_ENV=production (webpack optimizations)' ) . white }
242+ #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'RAILS_ENV=development by default for assets:precompile (avoids credentials)' ) . white }
243+ #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Use --rails-env=production for assets:precompile only (not server processes)' ) . white }
244+ #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Server processes controlled by Procfile.dev-prod-assets environment' ) . white }
245+ #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Optimized, minified bundles with CSS extraction' ) . white }
231246 #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'No HMR (static assets)' ) . white }
232- #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Slower recompilation' ) . white }
233247 #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Access at:' ) . white } #{ Rainbow ( 'http://localhost:3001/<route>' ) . cyan . underline }
234248 MODES
235249 end
236250 # rubocop:enable Metrics/AbcSize
237251
238- def run_production_like ( _verbose : false , route : nil )
252+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
253+ def run_production_like ( _verbose : false , route : nil , rails_env : nil )
239254 procfile = "Procfile.dev-prod-assets"
240255
241256 print_procfile_info ( procfile , route : route )
@@ -252,12 +267,33 @@ def run_production_like(_verbose: false, route: nil)
252267 route : route
253268 )
254269
255- # Precompile assets in production mode (includes pack generation automatically)
256- puts "🔨 Precompiling assets..."
270+ # Precompile assets with production webpack optimizations (includes pack generation automatically)
271+ env_vars = [ "NODE_ENV=production" ]
272+ env_vars << "RAILS_ENV=#{ rails_env } " if rails_env
273+ command = "#{ env_vars . join ( ' ' ) } bundle exec rails assets:precompile"
274+
275+ puts "🔨 Precompiling assets with production webpack optimizations..."
276+ puts ""
277+
278+ puts Rainbow ( "ℹ️ Asset Precompilation Environment:" ) . blue
279+ puts " • NODE_ENV=production → Webpack optimizations (minification, compression)"
280+ if rails_env
281+ puts " • RAILS_ENV=#{ rails_env } → Custom Rails environment for assets:precompile only"
282+ puts " • Note: RAILS_ENV=production requires credentials, database setup, etc."
283+ puts " • Server processes will use environment from Procfile.dev-prod-assets"
284+ else
285+ puts " • RAILS_ENV=development → Simpler Rails setup (no credentials needed)"
286+ puts " • Use --rails-env=production for assets:precompile step only"
287+ puts " • Server processes will use environment from Procfile.dev-prod-assets"
288+ puts " • Gets production webpack bundles without production Rails complexity"
289+ end
290+ puts ""
291+ puts "#{ Rainbow ( '💻 Running:' ) . blue } #{ command } "
292+ puts ""
257293
258294 # Capture both stdout and stderr
259295 require "open3"
260- stdout , stderr , status = Open3 . capture3 ( "RAILS_ENV=production NODE_ENV=production bundle exec rails assets:precompile" )
296+ stdout , stderr , status = Open3 . capture3 ( command )
261297
262298 if status . success?
263299 puts "✅ Assets precompiled successfully"
@@ -267,51 +303,69 @@ def run_production_like(_verbose: false, route: nil)
267303 puts "❌ Asset precompilation failed"
268304 puts ""
269305
270- # Display the actual error output
271- unless stderr . empty?
272- puts "#{ Rainbow ( '🚨 Error Output:' ) . red . bold } "
273- puts stderr
274- puts ""
275- end
306+ # Combine and display all output
307+ all_output = [ ]
308+ all_output << stdout unless stdout . empty?
309+ all_output << stderr unless stderr . empty?
276310
277- unless stdout . empty? && stdout . strip != stderr . strip
278- puts "#{ Rainbow ( '📋 Command Output:' ) . yellow . bold } "
279- puts stdout
311+ unless all_output . empty?
312+ puts Rainbow ( "📋 Full Command Output:" ) . red . bold
313+ puts Rainbow ( "─" * 60 ) . red
314+ all_output . each { |output | puts output }
315+ puts Rainbow ( "─" * 60 ) . red
280316 puts ""
281317 end
282318
283- puts "#{ Rainbow ( '💡 Common fixes:' ) . yellow . bold } "
319+ puts Rainbow ( "🛠️ To debug this issue:" ) . yellow . bold
320+ puts "#{ Rainbow ( '1.' ) . cyan } #{ Rainbow ( 'Run the command separately to see detailed output:' ) . white } "
321+ puts " #{ Rainbow ( command ) . cyan } "
322+ puts ""
323+ puts "#{ Rainbow ( '2.' ) . cyan } #{ Rainbow ( 'Add --trace for full stack trace:' ) . white } "
324+ puts " #{ Rainbow ( "#{ command } --trace" ) . cyan } "
325+ puts ""
326+ puts "#{ Rainbow ( '3.' ) . cyan } #{ Rainbow ( 'Or try with development webpack (faster, less optimized):' ) . white } "
327+ puts " #{ Rainbow ( 'NODE_ENV=development bundle exec rails assets:precompile' ) . cyan } "
328+ puts ""
329+
330+ puts Rainbow ( "💡 Common fixes:" ) . yellow . bold
284331
285332 # Provide specific guidance based on error content
286333 error_content = "#{ stderr } #{ stdout } " . downcase
287334
288335 if error_content . include? ( "secret_key_base" )
289- puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Missing secret_key_base:' ) . white . bold } Run #{ Rainbow ( 'bin/rails credentials:edit' ) . cyan } "
336+ puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Missing secret_key_base:' ) . white . bold } " \
337+ "Run #{ Rainbow ( 'bin/rails credentials:edit' ) . cyan } "
290338 end
291339
292- if error_content . include? ( "database" ) || error_content . include? ( "relation" ) || error_content . include? ( "table" )
293- puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Database issues:' ) . white . bold } Run #{ Rainbow ( 'bin/rails db:create db:migrate' ) . cyan } "
340+ if error_content . include? ( "database" ) || error_content . include? ( "relation" ) ||
341+ error_content . include? ( "table" )
342+ puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Database issues:' ) . white . bold } " \
343+ "Run #{ Rainbow ( 'bin/rails db:create db:migrate' ) . cyan } "
294344 end
295345
296346 if error_content . include? ( "gem" ) || error_content . include? ( "bundle" ) || error_content . include? ( "load error" )
297- puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Missing dependencies:' ) . white . bold } Run #{ Rainbow ( 'bundle install && npm install' ) . cyan } "
347+ puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Missing dependencies:' ) . white . bold } " \
348+ "Run #{ Rainbow ( 'bundle install && npm install' ) . cyan } "
298349 end
299350
300- if error_content . include? ( "webpack" ) || error_content . include? ( "module" ) || error_content . include? ( "compilation" )
301- puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Webpack compilation:' ) . white . bold } Check JavaScript/webpack errors above"
351+ if error_content . include? ( "webpack" ) || error_content . include? ( "module" ) ||
352+ error_content . include? ( "compilation" )
353+ puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Webpack compilation:' ) . white . bold } " \
354+ "Check JavaScript/webpack errors above"
302355 end
303356
304357 # Always show these general options
305- puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'General debugging :' ) . white } Run with #{ Rainbow ( '--trace' ) . cyan } for full stack trace"
306- puts " #{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Environment issues:' ) . white } Check #{ Rainbow ( 'config/environments/production.rb' ) . cyan } "
358+ puts "#{ Rainbow ( '•' ) . yellow } #{ Rainbow ( 'Environment config :' ) . white } " \
359+ " Check #{ Rainbow ( 'config/environments/production.rb' ) . cyan } "
307360
308361 puts ""
309- puts " #{ Rainbow ( ' ℹ️ Alternative for development:' ) . blue } "
362+ puts Rainbow ( " ℹ️ Alternative for development:" ) . blue
310363 puts " #{ Rainbow ( 'bin/dev static' ) . green } # Static assets without production optimizations"
311364 puts ""
312365 exit 1
313366 end
314367 end
368+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
315369
316370 def run_static_development ( procfile , verbose : false , route : nil )
317371 print_procfile_info ( procfile , route : route )
0 commit comments