Skip to content

Commit 921af01

Browse files
justin808claude
andcommitted
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 full example - 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 Aligns with Shakapacker PR #737 preventing_fouc.md documentation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent b3ce154 commit 921af01

File tree

1 file changed

+43
-12
lines changed

1 file changed

+43
-12
lines changed

docs/core-concepts/auto-bundling-file-system-based-automated-bundle-generation.md

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -522,23 +522,54 @@ As of version 13.3.4, bundles inside directories that match `config.components_s
522522

523523
#### 2. CSS not loading (FOUC - Flash of Unstyled Content)
524524

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`.
526526

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.
528528

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+
<% content_for :body_content do %>
535+
<%= react_component "NavigationBarApp", prerender: true %>
536+
537+
<div class="container">
538+
<%= yield %>
539+
</div>
540+
541+
<%= react_component "Footer", prerender: true %>
542+
<% end %>
543+
<!DOCTYPE html>
544+
<html>
545+
<head>
546+
<%= csrf_meta_tags %>
547+
<%= csp_meta_tag %>
548+
549+
<!-- All auto-appended stylesheets will be included here -->
550+
<%= stylesheet_pack_tag(media: 'all') %>
551+
<%= javascript_pack_tag(defer: true) %>
552+
</head>
553+
<body>
554+
<%= yield :body_content %>
555+
</body>
556+
</html>
557+
```
558+
559+
**Alternative**: If the `content_for` pattern doesn't fit your needs, disable auto-loading and manually specify packs:
560+
561+
```ruby
562+
# config/initializers/react_on_rails.rb
563+
config.auto_load_bundle = false
564+
```
530565

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';`
566+
**Additional Resources**:
536567

537-
**Key insight**: Choose your development mode based on your current needs:
568+
- **Complete FOUC prevention guide**: [Shakapacker Preventing FOUC documentation](https://github.com/shakacode/shakapacker/blob/master/docs/preventing_fouc.md)
569+
- **Working example**: [react-webpack-rails-tutorial PR #686](https://github.com/shakacode/react-webpack-rails-tutorial/pull/686)
570+
- **Related issue**: [Shakapacker #720](https://github.com/shakacode/shakapacker/issues/720)
538571

539-
- Use HMR for fastest development (accept FOUC)
540-
- Use static mode when testing styling without FOUC
541-
- Use production mode for final testing
572+
**Note**: HMR-related FOUC in development mode (dynamic CSS injection) is separate from this SSR auto-loading issue. See Shakapacker docs for details.
542573

543574
#### 3. "document is not defined" errors during SSR
544575

0 commit comments

Comments
 (0)