A fully working demo of React on Rails v15 on Rails 8, showcasing server-side rendering, auto-registration, and bundle splitting capabilities.
β Includes:
- Server-Side Rendering (SSR) - React components render on the server for faster initial page loads
- Auto-Registration - Components in
app/javascript/packs/ror_components/
are automatically discovered and registered - Bundle Splitting - Automatic code splitting for optimized loading performance
- CSS Modules - Scoped CSS with automatic class name generation
- Multiple Dev Modes - HMR, static, and production-like development servers
- Rails 8 Integration - Latest Rails version with modern asset pipeline
π Repo name: react_on_rails-demo-v15-ssr-auto-registration-bundle-splitting
π Part of the React on Rails Demo Series
# Install dependencies
bundle && yarn
# Generate auto-registration files
bundle exec rake react_on_rails:generate_packs
# Start development server
./bin/dev
Visit http://localhost:3000 to see the demo in action.
There's a bug in the react_on_rails:generate_packs
task with CSS modules (see #1768).
Problem: The generator creates invalid JavaScript syntax when handling CSS modules:
// β Invalid (generated)
import HelloWorld.module from '../ror_components/HelloWorld.module.css';
ReactOnRails.register({HelloWorld, HelloWorld.module});
Workaround: After running the generator, manually fix the generated files by removing CSS module imports from the server bundle:
// β
Fixed (manual)
import ReactOnRails from 'react-on-rails';
import HelloWorld from '../packs/ror_components/HelloWorld.jsx';
ReactOnRails.register({HelloWorld});
This demo has been manually fixed to work correctly with SSR.
This application showcases the following React on Rails v15 features:
- Automatic component discovery from
app/javascript/packs/ror_components/
- No manual bundle registration required
- Zero-config code splitting with Shakapacker nested_entries
- React components render on the server for better SEO and performance
- Isomorphic JavaScript - same code runs on client and server
- Node.js execution pools for efficient server rendering
- HelloWorld: Lightweight component (~5KB)
- HeavyMarkdownEditor: Heavy component (~300KB+) with markdown editing
- Automatic code splitting - users only download what they need
- Multiple dev modes: HMR, static, and production-like
- Hot Module Replacement for instant feedback
- Source maps for debugging
- CSS Modules support
- Rails 8.0.2 - Web framework (minimal setup, no asset pipeline)
- React 19.1.1 - UI library with modern features
- React on Rails 15.0.0 - Integration layer
- Shakapacker 8.3.0 - Webpack integration with auto-registration support
app/
controllers/
hello_world_controller.rb # Rails controller
views/
hello_world/
index.html.erb # HelloWorld page
markdown_editor.html.erb # Markdown editor page
layouts/
hello_world.html.erb # Layout (auto-bundle loading)
javascript/
packs/
ror_components/ # Auto-registration directory
HelloWorld.jsx # Simple React component
HelloWorld.module.css # CSS modules
HeavyMarkdownEditor.jsx # Complex component
HeavyMarkdownEditor.module.css
config/
initializers/
react_on_rails.rb # Auto-registration config
webpack/ # Webpack configurations
bin/
dev # Enhanced development script
config/initializers/react_on_rails.rb
ReactOnRails.configure do |config|
config.components_subdirectory = "ror_components" # Auto-discovery
config.auto_load_bundle = true # Auto-loading
config.server_bundle_js_file = "server-bundle.js" # SSR bundle
end
config/shakapacker.yml
default: &default
nested_entries: true # Required for auto-registration
source_entry_path: packs
This repository was built step-by-step with educational commits:
- Rails 8 Base Setup - Minimal Rails app without JS frameworks
- Shakapacker Installation - Webpack integration with nested_entries
- React on Rails Setup - Install gem and generate initial files
- Enhanced Dev Script - Multi-mode development support
- Auto-Registration - Enable automatic component discovery
- SSR Enablement - Server-side rendering for better performance
- Navigation & Routing - Basic app navigation structure
- Bundle Splitting Demo - Heavy component with automatic splitting
Each commit includes detailed explanations of what was added and why.
./bin/dev
- Hot Module Replacement for instant updates
- Fast recompilation on file changes
- May have FOUC (Flash of Unstyled Content)
- Best for: Active development
./bin/dev static
- No HMR but with auto-recompilation
- CSS extracted to separate files (no FOUC)
- Development environment with source maps
- Best for: Testing without HMR side effects
./bin/dev prod
- Optimized bundles with minification
- Production-like environment
- Runs on port 3001
- Best for: Testing production builds
You can analyze bundle sizes with:
# Generate production bundles
RAILS_ENV=production NODE_ENV=production bin/shakapacker
# Check bundle sizes
ls -la public/packs/js/
Expected results:
HelloWorld-*.js
- Small bundle (~5-10KB)HeavyMarkdownEditor-*.js
- Large bundle (~300KB+)server-bundle.js
- Server rendering bundle
- Visit
/hello_world
- should load HelloWorld component - Check network tab - only HelloWorld bundle loads
- Visit
/markdown_editor
- should load markdown editor - Check network tab - HeavyMarkdownEditor bundle loads separately
- Disable JavaScript in browser
- Visit pages - content should still be visible
- View page source - React HTML should be pre-rendered
- Open browser DevTools β Network tab
- Visit HelloWorld page - note small bundle size
- Navigate to Markdown Editor - note additional bundle loads
- Go back to HelloWorld - no additional downloads needed
For production deployment:
- Precompile assets:
RAILS_ENV=production bundle exec rails assets:precompile
- Set environment variables for your deployment platform
- Configure database for production
- Set up Node.js for server-side rendering
This is a tutorial application, but improvements are welcome:
- Fork the repository
- Create a feature branch
- Make your changes with clear commit messages
- Submit a pull request
Built with β€οΈ using React on Rails v15