@@ -79,6 +79,12 @@ def invoke_generators
7979 else
8080 invoke "react_on_rails:react_no_redux" , [ ] , { typescript : options . typescript? }
8181 end
82+ setup_react_dependencies
83+ end
84+
85+ def setup_react_dependencies
86+ add_js_dependencies
87+ install_js_dependencies
8288 end
8389
8490 # NOTE: other requirements for existing files such as .gitignore or application.
@@ -412,6 +418,118 @@ def create_typescript_config
412418 puts Rainbow ( "✅ Created tsconfig.json" ) . green
413419 end
414420
421+ def add_js_dependencies
422+ add_react_on_rails_package
423+ add_react_dependencies
424+ add_css_dependencies
425+ add_dev_dependencies
426+ end
427+
428+ def add_react_on_rails_package
429+ major_minor_patch_only = /\A \d +\. \d +\. \d +\z /
430+
431+ # Try to use package_json gem first, fall back to direct npm commands
432+ react_on_rails_pkg = if ReactOnRails ::VERSION . match? ( major_minor_patch_only )
433+ [ "react-on-rails@#{ ReactOnRails ::VERSION } " ]
434+ else
435+ puts "Adding the latest react-on-rails NPM module. " \
436+ "Double check this is correct in package.json"
437+ [ "react-on-rails" ]
438+ end
439+
440+ puts "Installing React on Rails package..."
441+ return if add_npm_dependencies ( react_on_rails_pkg )
442+
443+ puts "Using direct npm commands as fallback"
444+ success = system ( "npm" , "install" , *react_on_rails_pkg )
445+ handle_npm_failure ( "react-on-rails package" , react_on_rails_pkg ) unless success
446+ end
447+
448+ def add_react_dependencies
449+ puts "Installing React dependencies..."
450+ react_deps = %w[
451+ react
452+ react-dom
453+ @babel/preset-react
454+ prop-types
455+ babel-plugin-transform-react-remove-prop-types
456+ babel-plugin-macros
457+ ]
458+ return if add_npm_dependencies ( react_deps )
459+
460+ success = system ( "npm" , "install" , *react_deps )
461+ handle_npm_failure ( "React dependencies" , react_deps ) unless success
462+ end
463+
464+ def add_css_dependencies
465+ puts "Installing CSS handling dependencies..."
466+ css_deps = %w[
467+ css-loader
468+ css-minimizer-webpack-plugin
469+ mini-css-extract-plugin
470+ style-loader
471+ ]
472+ return if add_npm_dependencies ( css_deps )
473+
474+ success = system ( "npm" , "install" , *css_deps )
475+ handle_npm_failure ( "CSS dependencies" , css_deps ) unless success
476+ end
477+
478+ def add_dev_dependencies
479+ puts "Installing development dependencies..."
480+ dev_deps = %w[
481+ @pmmmwh/react-refresh-webpack-plugin
482+ react-refresh
483+ ]
484+ return if add_npm_dependencies ( dev_deps , dev : true )
485+
486+ success = system ( "npm" , "install" , "--save-dev" , *dev_deps )
487+ handle_npm_failure ( "development dependencies" , dev_deps , dev : true ) unless success
488+ end
489+
490+ def install_js_dependencies
491+ # Detect which package manager to use
492+ success = if File . exist? ( File . join ( destination_root , "yarn.lock" ) )
493+ system ( "yarn" , "install" )
494+ elsif File . exist? ( File . join ( destination_root , "pnpm-lock.yaml" ) )
495+ system ( "pnpm" , "install" )
496+ elsif File . exist? ( File . join ( destination_root , "package-lock.json" ) ) ||
497+ File . exist? ( File . join ( destination_root , "package.json" ) )
498+ # Use npm for package-lock.json or as default fallback
499+ system ( "npm" , "install" )
500+ else
501+ true # No package manager detected, skip
502+ end
503+
504+ unless success
505+ GeneratorMessages . add_warning ( <<~MSG . strip )
506+ ⚠️ JavaScript dependencies installation failed.
507+
508+ This could be due to network issues or missing package manager.
509+ You can install dependencies manually later by running:
510+ • npm install (if using npm)
511+ • yarn install (if using yarn)
512+ • pnpm install (if using pnpm)
513+ MSG
514+ end
515+
516+ success
517+ end
518+
519+ def handle_npm_failure ( dependency_type , packages , dev : false )
520+ install_command = dev ? "npm install --save-dev" : "npm install"
521+ GeneratorMessages . add_warning ( <<~MSG . strip )
522+ ⚠️ Failed to install #{ dependency_type } .
523+
524+ The following packages could not be installed automatically:
525+ #{ packages . map { |pkg | " • #{ pkg } " } . join ( "\n " ) }
526+
527+ This could be due to network issues or missing package manager.
528+ You can install them manually later by running:
529+ #{ install_command } #{ packages . join ( ' ' ) }
530+ MSG
531+ end
532+
415533 # Removed: Shakapacker auto-installation logic (now explicit dependency)
416534
417535 # Removed: Shakapacker 8+ is now required as explicit dependency
0 commit comments