Architecture

    SSR vs CSR

    Mis à jour le 1 février 2026

    Définition

    SSR (Server-Side Rendering) génère le HTML complet sur le serveur, facilitant l'indexation SEO et le scraping. CSR (Client-Side Rendering) génère le contenu via JavaScript dans le navigateur, nécessitant un headless browser pour le scraping. Les frameworks modernes (Next.js, Nuxt) combinent les deux approches.

    Deep Dive

    SSR vs CSR : impact sur le crawling et le SEO

    Comparatif technique

    | Aspect | SSR | CSR |

    |--------|-----|-----|

    | HTML initial | Complet | Minimal (shell) |

    | Temps au contenu | Rapide | Après JS load |

    | SEO / Crawling | Excellent | Problématique |

    | Interactivité | Après hydration | Immédiate |

    | Charge serveur | Plus élevée | Minimale |

    Évolution des architectures

    **Génération 1 : PHP/Rails (Pure SSR)**

  1. HTML rendu à chaque requête
  2. Simple à scraper
  3. **Génération 2 : React SPA (Pure CSR)**

  4. JavaScript génère tout le DOM
  5. Nécessite headless browser
  6. **Génération 3 : Next.js/Nuxt (Hybride)**

  7. SSR pour le premier rendu
  8. Hydration côté client
  9. ISR (Incremental Static Regeneration)
  10. Détection du mode de rendu

    Pour savoir si un site utilise CSR :

    1. Désactiver JavaScript dans le navigateur

    2. Si la page est vide → CSR pur

    3. Si le contenu apparaît → SSR ou SSG

    Code Playground

    Détection automatique du mode de rendu et sélection de la stratégie de scraping optimale

    python
    # Détection automatique SSR vs CSR et stratégie de scraping adaptée
    import httpx
    from playwright.async_api import async_playwright
    from selectolax.parser import HTMLParser
    
    async def detect_rendering_mode(url: str) -> dict:
        """Détecte si un site utilise SSR ou CSR"""
        
        # 1. Fetch HTML brut (sans JavaScript)
        async with httpx.AsyncClient() as client:
            response = await client.get(url)
            raw_html = response.text
        
        raw_tree = HTMLParser(raw_html)
        raw_text_content = raw_tree.body.text(strip=True) if raw_tree.body else ""
        
        # 2. Fetch avec JavaScript (Playwright)
        async with async_playwright() as p:
            browser = await p.chromium.launch()
            page = await browser.new_page()
            await page.goto(url, wait_until='networkidle')
            rendered_html = await page.content()
            await browser.close()
        
        rendered_tree = HTMLParser(rendered_html)
        rendered_text_content = rendered_tree.body.text(strip=True) if rendered_tree.body else ""
        
        # 3. Comparer les contenus
        raw_length = len(raw_text_content)
        rendered_length = len(rendered_text_content)
        
        content_ratio = raw_length / rendered_length if rendered_length > 0 else 0
        
        # Heuristique : si le HTML brut contient moins de 30% du contenu rendu
        is_csr = content_ratio < 0.3
        
        return {
            'url': url,
            'mode': 'CSR' if is_csr else 'SSR',
            'raw_content_length': raw_length,
            'rendered_content_length': rendered_length,
            'content_ratio': round(content_ratio, 2),
            'recommendation': 'Use headless browser' if is_csr else 'Simple HTTP fetch is sufficient'
        }
    
    async def adaptive_scrape(url: str):
        """Scrape adaptatif selon le mode de rendu détecté"""
        mode_info = await detect_rendering_mode(url)
        
        if mode_info['mode'] == 'SSR':
            # Scraping simple et rapide
            async with httpx.AsyncClient() as client:
                response = await client.get(url)
                return HTMLParser(response.text)
        else:
            # Scraping avec JavaScript rendering
            async with async_playwright() as p:
                browser = await p.chromium.launch()
                page = await browser.new_page()
                await page.goto(url, wait_until='networkidle')
                html = await page.content()
                await browser.close()
                return HTMLParser(html)

    Avis d'Expert 2026

    La tendance 2026 est au "Partial Hydration" et aux "Server Components" (React) qui complexifient encore la donne. Les scrapers professionnels maintiennent des profils par domaine indiquant le mode de rendu optimal. L'idéal reste de détecter automatiquement et d'utiliser la méthode la plus légère possible.

    Besoin d'aide sur SSR vs CSR ?

    Nos experts peuvent vous accompagner sur vos projets de crawling et d'optimisation GEO.

    Contactez l'expert Crawlers.fr
    4.6/5 (73 avis d'experts)