Server-side rendering (SSR): ce este, de ce contează pentru SEO, cum o faci
Server-side rendering livrează HTML-ul gata făcut din server, nu un schelet umplut de JavaScript. Pentru SEO, diferența între indexat și invizibil.
Cuprins
Server-side rendering (SSR) înseamnă că HTML-ul paginii este construit pe server și trimis browserului gata făcut, în loc să fie generat în browser prin JavaScript. Pentru un site care vrea să fie indexat de Google, asta este diferența între a fi văzut din prima cerere și a aștepta crawlerul să execute JavaScript-ul. SSR nu e un detaliu tehnic; este o decizie care se vede direct în rezultatele căutării.
Termenul a căpătat sens modern odată cu single-page applications de la mijlocul anilor 2010, când frameworkuri ca React și Angular au mutat randarea în browser și au descoperit că Googlebot indexa goluri. SSR aduce randarea înapoi pe server, păstrând în același timp interactivitatea bogată a unei aplicații JavaScript prin hydration.
Ce este SSR mai exact?
O strategie de livrare a paginii web în care serverul rulează codul aplicației (de obicei JavaScript), construiește arborele HTML pentru ruta cerută și trimite acel HTML browserului ca primă cerere. Browserul afișează imediat conținutul; apoi încarcă bundle-urile JavaScript și le „atașează" elementelor deja randate pentru a face pagina interactivă. Pasul al doilea se numește hydration și e ce diferențiază SSR de o pagină statică obișnuită.
Trei termeni înrudiți, care se confundă des:
- CSR (client-side rendering). Serverul trimite un schelet HTML gol și un bundle JavaScript mare; browserul construiește totul pe loc. Răspândit în SPA-uri vechi. Văzut prost de Googlebot dacă bundle-ul depinde de cereri API.
- SSG (static site generation). Paginile sunt randate o singură dată, la build time, în fișiere HTML statice. Excelent pentru conținut care nu se schimbă des (documentație, blog cu cadență mică). Slab pentru date dinamice.
- SSR (server-side rendering). Paginile sunt randate la fiecare cerere (sau cu un layer de cache între), pe server. Bun pentru conținut care se schimbă, dar trebuie să fie indexat.
În practică, multe stack-uri moderne combină cele trei: prerender la build pentru paginile statice, SSR pentru cele dinamice, CSR pentru zonele autentificate. Angular Universal, Next.js, Nuxt, Remix, SolidStart, toate oferă această combinație.
Cum funcționează SSR din spate?
Pe scurt, un proces Node (sau Deno, sau Bun) ascultă pe un port intern. Când vine o cerere, framework-ul ridică în memorie arborele de componente al rutei cerute, le execută cu datele din cerere, serializează rezultatul ca HTML, îl injectează într-un template și trimite răspunsul. Procesul rămâne viu între cereri și reutilizează codul; nu pornește de la zero la fiecare GET.
În producție, lanțul tipic este nginx → proces SSR → backend API:
- nginx termină TLS, servește fișierele statice (CSS, JavaScript bundles, imagini) direct de pe disc, și face proxy pentru cererile HTML către procesul SSR. Adaugă headere de cache (
Cache-Control,stale-while-revalidate) ca să nu re-randeze aceeași pagină la fiecare cititor. - Procesul SSR rulează ca serviciu systemd, restartat automat, cu o limită de memorie strictă. Pe crawlerra.com folosim
--max-old-space-size=192pentru că un proces Node fără limită mănâncă lent toată memoria VPS-ului. - Backendul este interogat sincron, în timpul randării. Asta înseamnă că SSR-ul depinde de viteza API-ului. Un endpoint care răspunde în 800ms îți strică tot avantajul SSR; trebuie cache la nivelul API sau o strategie de pre-fetch.
Care sunt capcanele frecvente?
- Cod care presupune
windowsaudocument. Pe server nu există browser. Apelurile lalocalStorage,window.matchMedia,document.bodytrebuie ghidate cuisPlatformBrowser()(Angular) sautypeof window !== 'undefined'(oriunde altunde). Dacă uiți o singură referință, întregul proces SSR cade pe acea rută. - Diferență între server și client la hydration. Dacă serverul randează un timestamp și clientul îl re-randează cu o oră de fus orar diferită, hydration „rupe" și browserul face un re-render brutal. Folosește datele primite, nu le recalcula în client.
- Memory leaks în procesul SSR. Procesul rulează ore în șir. Orice abonament reactiv care nu se închide după randarea unei pagini se acumulează. Monitorizează RSS-ul procesului în stack-ul de observabilitate; o creștere liniară zilnic înseamnă un leak.
- Cache fără invalidare. Cache-ul nginx cu
max-age=3600e ușor de pus. Inviarea lui când publicăm un articol nou e ce uită majoritatea. Foloseștestale-while-revalidatepentru tranzacții lente și flush explicit la publish. - API lent + SSR sincron. SSR-ul ține clientul în așteptare cât timp randează. Dacă API-ul răspunde în 1,5s, prima cerere durează cel puțin 1,5s. Streaming SSR (chunked HTML) sau cache agresiv la nivel de API sunt soluțiile; nu „mai multă putere de calcul".
Cum folosim SSR la crawlerra?
Tot ce e public pe crawlerra.com rulează Angular 19 SSR pe portul intern 4002, în spatele nginx. Procesul SSR este un singur serviciu systemd cu limită de 192 MB heap1; cache-ul HTTP face restul muncii (5 minute browser, 1 oră proxy, 24 ore stale-while-revalidate). Pentru articolul pe care îl citești acum, întregul corp HTML (47 KB)2 ajunge la Googlebot la prima cerere, fără să mai aștepte JavaScript.
Strategia per cluster de pagini:
- Prerender la build pentru rutele care nu depind de date dinamice:
/,/en,/privacy. Patru pagini, generate o singură dată în pipeline-ul de build. - SSR la cerere pentru rute care depind de baza de date:
/blog,/blog/:slug,/dictionar,/dictionar/:slug. Procesul SSR interoghează backendul Spring Boot pe portul 8084 pentru fiecare cerere care iese din cache. - CSR în spatele autentificării pentru zonele de admin (
/admin/*) și portal client (/portal/*). Acolo SSR nu aduce nimic pentru SEO (suntnoindexoricum) și ar complica fluxul de autentificare. Detalii practice în ghidul nostru despre Angular SSR pentru produse reale.
Cum verifici că SSR funcționează corect?
Testul de bază durează zece secunde. Rulează curl -sS https://your-site.com/some-page și caută în răspuns un titlu vizibil sau un paragraf concret. Dacă îl găsești, Googlebot îl va găsi și el. Dacă vezi doar elementul rădăcină al aplicației și script-uri, pagina ta este CSR mascată în SSR, iar indexarea va suferi.
Pentru o verificare serioasă, treci pagina prin Google Rich Results Test sau prin Search Console („URL Inspection" → „Test Live URL"). Acolo vezi exact ce randează Google după execuția JavaScript-ului. Dacă JSON-LD-ul tău e prezent în randul „rendered HTML", schema markup va fi indexat; dacă nu, șansa e mare să fii lipit pe un bundle care nu rulează corect pe partea serverului. Verifică în paralel că sitemap.xml include URL-urile generate dinamic și că hreflang-ul e setat dacă servești în mai multe limbi; altfel SSR-ul randează corect pagini pe care Google nu le va găsi sau le va indexa pe limba greșită.
- Limita de heap
--max-old-space-size=192a fost setată după ce procesul SSR a depășit 800 MB RSS în 48 de ore din cauza unui abonament reactiv care nu se închidea.[ops.angular_memory] - Mărimea HTML-ului SSR pentru un articol din blog, măsurată cu
curl -sS https://crawlerra.com/blog/cum-scriem-articolele | wc -c.[crawlerra.ssr_body_size]
Întrebări frecvente
SSR, SSG sau CSR, care e alegerea corectă pentru un produs nou?
SSR pentru orice e indexat de Google, SSG dacă pagina nu se schimbă des, CSR doar în spatele unui login. Marketing site, blog, catalog public, magazin: SSR. Documentație, landing static, single-page-marketing: SSG. Dashboard intern, aplicație autentificată, panou de admin: CSR. Regula nu e religioasă; e pragmatică.
Are SSR sens pentru un blog mic sau un MVP?
Da, pentru că prima impresie a Googlebot-ului contează din ziua unu. Costul suplimentar al SSR la scară mică e neglijabil (un proces Node de ~200 MB RAM), iar diferența la indexare e brutală. Dacă blogul devine mare mai târziu, deja ai infrastructura potrivită; dacă rămâne mic, nu ai pierdut nimic.
Cât costă să rulezi SSR în producție?
Sub 10 EUR pe lună pentru un site cu trafic moderat, pe un VPS de 1 GB RAM. Procesul Node ține pagina pre-randată în cache pentru câteva minute; nginx servește din cache pentru utilizatorii repetați. Cea mai mare cheltuială ascunsă nu e CPU-ul, ci atenția: trebuie să monitorizezi memoria procesului SSR (am rulat --max-old-space-size=192 pe crawlerra.com pentru un motiv).
SSR strică viteza percepută de utilizator?
Nu, de obicei o îmbunătățește. Largest Contentful Paint apare mai devreme pentru că serverul livrează conținut deja randat, nu un schelet gol. Time to Interactive poate fi puțin mai târziu (browserul tot trebuie să încarce JavaScript-ul pentru hydration), dar utilizatorul citește deja conținutul în timp ce JavaScript-ul se încarcă în fundal.
Cum verifici că SSR funcționează corect?
Cu curl -A "Googlebot" https://your-site.com/ și caută conținutul în răspuns. Dacă vezi HTML-ul complet cu titluri, paragrafe și meta tag-uri, SSR merge. Dacă vezi doar <app-root></app-root> și o grămadă de script-uri, pagina ta vorbește doar cu browserele care execută JavaScript, ceea ce Googlebot face cu întârziere de ore sau zile.