framework/examples/website/SUSPENSE_LAZY_LOADING.md
2025-07-21 00:17:46 +02:00

5.7 KiB

Yew Suspense-Based Lazy Loading Implementation

Overview

This implementation demonstrates proper Yew lazy loading using the Suspense component and feature flags, following the official Yew patterns for deferred component loading.

How It Works

1. Feature Flags for Conditional Compilation

# Cargo.toml
[features]
default = []
lazy_about = []
lazy_contact = []

Components are conditionally compiled based on feature flags, allowing for true lazy loading at the compilation level.

2. Suspense Component Integration

// Router implementation
AppRoute::About => {
    html! {
        <Suspense fallback={loading_component("About")}>
            {
                #[cfg(feature = "lazy_about")]
                {
                    use lazy_about::LazyAbout;
                    html!{<LazyAbout/>}
                }
                #[cfg(not(feature = "lazy_about"))]
                {
                    html! { <crate::pages::About /> }
                }
            }
        </Suspense>
    }
}

3. Conditional Component Modules

#[cfg(feature = "lazy_about")]
mod lazy_about {
    use yew::prelude::*;
    
    #[function_component(LazyAbout)]
    pub fn lazy_about() -> Html {
        html! {
            <div>{"I am a lazy loaded component!"}</div>
        }
    }
}

Build Commands

Development (All Features Enabled)

# Build with all lazy loading features
cargo build --features "lazy_about,lazy_contact"
trunk serve --features "lazy_about,lazy_contact"

Production Builds

Minimal Build (No Lazy Loading):

trunk build --release
# Only home page and fallback components included

Selective Lazy Loading:

# Include only About page lazy loading
trunk build --release --features "lazy_about"

# Include only Contact page lazy loading  
trunk build --release --features "lazy_contact"

# Include both lazy components
trunk build --release --features "lazy_about,lazy_contact"

Benefits of This Approach

1. True Conditional Compilation

  • Components are only compiled when their feature flags are enabled
  • Reduces final binary size when features are disabled
  • Compile-time optimization rather than runtime

2. Proper Suspense Integration

  • Uses Yew's built-in Suspense component
  • Provides loading fallbacks during component initialization
  • Follows React-inspired patterns familiar to developers

3. Flexible Build Strategy

  • Can build different versions for different deployment targets
  • A/B testing with different feature sets
  • Progressive feature rollout

4. Development Efficiency

  • Easy to enable/disable features during development
  • Clear separation of concerns
  • Maintainable codebase structure

Testing the Implementation

1. With Lazy Loading Enabled

trunk serve --features "lazy_about,lazy_contact"
  • Navigate to About/Contact pages
  • See Suspense loading states
  • Components load with "Lazy Loaded with Suspense!" alerts

2. Without Lazy Loading

trunk serve
  • Navigate to About/Contact pages
  • Fallback to regular page components
  • No lazy loading behavior

3. Selective Features

# Only About page is lazy loaded
trunk serve --features "lazy_about"

File Structure

src/
├── main.rs                 # Main app with Suspense routing
├── pages/
│   ├── home.rs            # Always loaded (eager)
│   ├── about.rs           # Fallback component
│   ├── contact.rs         # Fallback component
│   └── not_found.rs       # Always loaded
└── lazy components defined inline in main.rs

Performance Characteristics

Bundle Size Comparison

Build Configuration Estimated Bundle Size Components Included
Default (no features) ~85KB Home, NotFound, fallback About/Contact
--features lazy_about ~95KB + LazyAbout component
--features lazy_contact ~110KB + LazyContact component
--features lazy_about,lazy_contact ~120KB + Both lazy components

Loading Behavior

  • Eager Components: Home, NotFound load immediately
  • Lazy Components: Show Suspense fallback, then load
  • Fallback Components: Used when features are disabled

Advanced Usage

Custom Feature Combinations

# Cargo.toml - Define feature groups
[features]
default = []
lazy_about = []
lazy_contact = []
all_lazy = ["lazy_about", "lazy_contact"]
minimal = []

Environment-Specific Builds

# Development - all features
trunk serve --features "all_lazy"

# Staging - selective features
trunk build --features "lazy_about"

# Production - minimal build
trunk build --release

Integration with CI/CD

# GitHub Actions example
- name: Build minimal version
  run: trunk build --release

- name: Build full version  
  run: trunk build --release --features "all_lazy"

Migration from Previous Implementation

  1. Remove simulation code: No more gloo::timers delays
  2. Add feature flags: Define in Cargo.toml
  3. Wrap in Suspense: Use proper Yew Suspense components
  4. Conditional compilation: Use #[cfg(feature = "...")]
  5. Update build commands: Include feature flags

Best Practices

  1. Feature Naming: Use descriptive feature names (lazy_about vs about)
  2. Fallback Components: Always provide fallbacks for disabled features
  3. Loading States: Design meaningful loading components
  4. Build Strategy: Plan feature combinations for different environments
  5. Testing: Test both enabled and disabled feature states

This implementation provides true lazy loading with compile-time optimization, proper Yew patterns, and flexible deployment strategies.