You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Document content_for pattern to prevent FOUC with SSR and auto_load_bundle
Fixes#1864
When using auto_load_bundle = true with server-side rendering, there's a
chicken-and-egg problem: stylesheets must load in the <head>, but
react_component calls in <body> trigger auto-appends after the head has
rendered, causing FOUC (Flash of Unstyled Content).
This commit documents the content_for workaround pattern and references
the comprehensive Shakapacker FOUC prevention guide (PR #737).
Key improvements:
- Explains the root cause of FOUC with SSR + auto_load_bundle
- Documents the content_for :body_content pattern with execution flow
- Added step-by-step comments showing Rails execution order
- References Shakapacker's comprehensive FOUC prevention documentation
- Links to working example in react-webpack-rails-tutorial PR #686
- Provides alternative solution (disable auto_load_bundle)
- Clarifies that HMR FOUC is separate from this SSR issue
- Addresses code review feedback from PR #1865 comment #3412140475
Aligns with Shakapacker PR #737 preventing_fouc.md documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Copy file name to clipboardExpand all lines: docs/core-concepts/auto-bundling-file-system-based-automated-bundle-generation.md
+47-12Lines changed: 47 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -522,23 +522,58 @@ As of version 13.3.4, bundles inside directories that match `config.components_s
522
522
523
523
#### 2. CSS not loading (FOUC - Flash of Unstyled Content)
524
524
525
-
**Problem**: Components load but CSS styles are missing or delayed.
525
+
**Problem**: Components load but CSS styles are missing or delayed, particularly with server-side rendering and `auto_load_bundle = true`.
526
526
527
-
**Important**: FOUC (Flash of Unstyled Content) **only occurs with HMR (Hot Module Replacement)**. Static and production modes work perfectly without FOUC.
527
+
**Root Cause**: When using `auto_load_bundle = true`, `react_component` calls automatically invoke `append_stylesheet_pack_tag` during rendering. However, Shakapacker requires these appends to execute BEFORE the main `stylesheet_pack_tag` in your layout's `<head>`. Since Rails renders the layout's `<head>` before the `<body>` (where `react_component` calls typically occur), the appends happen too late, causing FOUC.
528
528
529
-
**Solutions**:
529
+
**Solution**: Use the `content_for :body_content` pattern documented in Shakapacker's [Preventing FOUC guide](https://github.com/shakacode/shakapacker/blob/master/docs/preventing_fouc.md#the-content_for-body_content-pattern).
530
+
531
+
This pattern renders your body content first, ensuring all `react_component` auto-appends execute before the `<head>` renders:
532
+
533
+
```erb
534
+
<%# Step 1: This block executes first, capturing content AND triggering auto-appends %>
<%# Step 2: Head renders with all accumulated stylesheet/JS appends %>
551
+
<%= stylesheet_pack_tag(media: 'all') %>
552
+
<%= javascript_pack_tag(defer: true) %>
553
+
</head>
554
+
<body>
555
+
<%# Step 3: Finally, the captured body_content is rendered here %>
556
+
<%= yield :body_content %>
557
+
</body>
558
+
</html>
559
+
```
560
+
561
+
**Note**: While defining body content before `<!DOCTYPE html>` may seem counter-intuitive, Rails processes the `content_for` block first (capturing content and triggering appends), then renders the HTML in proper document order.
562
+
563
+
**Alternative**: If the `content_for` pattern doesn't fit your needs, disable auto-loading and manually specify packs:
564
+
565
+
```ruby
566
+
# config/initializers/react_on_rails.rb
567
+
config.auto_load_bundle = false
568
+
```
530
569
531
-
- **Development with HMR** (`./bin/dev`): FOUC is expected behavior due to dynamic CSS injection - **not a bug**
532
-
- **Development static** (`./bin/dev static`): No FOUC - CSS is extracted to separate files like production
533
-
- **Production** (`./bin/dev prod`): No FOUC - CSS is extracted and optimized
534
-
- **Layout**: Verify your layout includes empty `<%= stylesheet_pack_tag %>` placeholder for CSS injection
535
-
- **Component imports**: Check that CSS files are properly imported: `import styles from './Component.module.css';`
570
+
**Additional Resources**:
536
571
537
-
**Key insight**: Choose your development mode based on your current needs:
0 commit comments