React i SEO
React domyślnie renderuje po stronie klienta, więc roboty indeksujące widzą pustą skorupę, dopóki JavaScript nie zostanie uruchomiony. Oto, jak Google faktycznie przetwarza aplikacje React, którą strategię renderowania wybrać oraz jak naprawić routing, metadane i pułapkę duplikatów treści związaną z limitem czasu renderowania.
React nie jest zły dla SEO — ale domyślne renderowanie po stronie klienta już tak. Po wyjęciu z pudełka (CRA, Vite + React) serwer wysyła pustą skorupę, a przeglądarka buduje stronę, więc roboty indeksujące nie widzą nic, dopóki JavaScript nie zostanie uruchomiony. Google może renderować React za pomocą swojej usługi Web Rendering Service, ale renderowanie jest kolejkowe, opóźnione i może przekroczyć limit czasu — Gary Illyes pokazał, że przekroczenia limitu czasu renderowania pozostawiają strony tylko ze szkieletem, które są oznaczane jako duplikaty. Kontrakty renderowania robotów AI różnią się w zależności od dostawcy, więc treść tylko CSR dodaje ryzyko pokrycia. Rozwiązaniem jest strategia renderowania: SSR lub SSG (najłatwiej Next.js lub Remix) umieszcza treść w początkowym HTML, nawodnioną za pomocą hydrateRoot (nie createRoot), aby dane wyjściowe serwera i klienta były dokładnie takie same. Następnie użyj routingu API History, prawdziwych linków <a href>, poprawnych kodów statusu i metadanych odpowiednich do wersji: React 19 natywnie podnosi <title>/<meta>/<link>, w przeciwnym razie react-helmet-async (nigdy oryginalny, nieutrzymywany react-helmet).
TL;DR — React nie jest zły dla SEO — ale sposób, w jaki większość aplikacji React jest zbudowana, jest. Domyślnie React buduje stronę w przeglądarce odwiedzającego, więc gdy wyszukiwarka po raz pierwszy pobiera Twój adres URL, otrzymuje prawie pustą stronę. Google zwykle może uzupełnić braki, uruchamiając Twój JavaScript, ale jest to wolniejsze i bardziej ryzykowne niż przekazanie gotowego HTML. Rozwiązaniem jest renderowanie stron na serwerze lub w czasie budowania — zwykle za pomocą frameworka takiego jak Next.js.
Dlaczego React jest inny
Większość stron internetowych — na przykład blog WordPress — wysyła wyszukiwarce kompletną stronę:
serwer buduje HTML i wysyła go, z nagłówkiem włącznie. Standardowa aplikacja React robi
coś odwrotnego. Serwer wysyła prawie pustą powłokę (zasadniczo pusty <div>),
a następnie JavaScript uruchamia się w przeglądarce, aby zbudować prawdziwą stronę.
To świetnie sprawdza się w przypadku płynnych, przypominających aplikacje doświadczeń. To problem dla SEO, ponieważ pierwszą rzeczą, którą pobiera robot indeksujący, jest ta pusta powłoka. Twoje treści jeszcze tam nie ma — pojawia się dopiero po uruchomieniu JavaScript.
Czy Google nie może po prostu uruchomić JavaScript?
Tak — Google uruchamia prawdziwą, aktualną wersję Chrome w tle i może wykonać Twój JavaScript, aby zobaczyć gotową stronę. Więc treści React mogą być indeksowane. Dowód potwierdzający to twierdzenie Googlebot uses an evergreen Chromium rendering engine and can execute JavaScript. Zakres: Google Search; successful execution still depends on accessible resources and application behavior. Poziom ufności: wysoki · Zweryfikowano: Google: JavaScript SEO basics
Ale są pewne zastrzeżenia:
- To jest opóźnione. Google wykonuje renderowanie później, w osobnym kroku, który jest umieszczany w kolejce. Więc Twoje treści mogą pojawiać się w wynikach wyszukiwania dłużej.
- To może zawieść. Jeśli Twoja strona wolno ładuje swoje treści, renderer Google może zrezygnować, zanim treści się pojawią — i zaindeksować prawie pustą stronę.
- Inne roboty indeksujące są różne. Bing radzi sobie z JavaScript mniej niezawodnie, a dostawcy AI nie publikują jednego wspólnego standardu renderowania. Każdy robot, który pobiera tylko początkowy HTML, zobaczy domyślną aplikację React jako pustą.
Proste rozwiązanie
Umieść swoje treści w HTML zanim trafią do przeglądarki. Są dwa sposoby:
- Renderowanie po stronie serwera (SSR) — serwer buduje pełną stronę dla każdego żądania.
- Statyczne generowanie witryny (SSG) — strony są budowane do gotowego HTML z wyprzedzeniem. Dowód potwierdzający to twierdzenie React supports server rendering APIs and can be used by frameworks that generate HTML outside the browser. Zakres: React server APIs; build-time generation is a framework/build-system capability rather than a React mode by itself. Poziom ufności: wysoki · Zweryfikowano: React: Server APIs
Najłatwiejsza droga do obu to Next.js, framework zbudowany na React, który robi to za Ciebie. (Remix to kolejna dobra opcja.) Dzięki SSR lub SSG Twoja witryna React przekazuje robotom indeksującym kompletną stronę — i jest tak przyjazna dla wyszukiwarek jak każda normalna witryna.
Kilka innych rzeczy, które warto zrobić dobrze
- Używaj normalnie wyglądających adresów URL (
/products), a nie adresów z hashem (/#/products) — Google nie może niezawodnie indeksować tych z hashem. - Twórz prawdziwe linki (
<a href>), a nie klikalne<div>y. - Nadaj każdej stronie własny tytuł i opis, które aktualizują się, gdy strona się zmienia.
Chcesz głębszą wersję — jak faktycznie działa renderer Google, pułapka limitu czasu renderowania, która tworzy zduplikowane strony, porównanie strategii renderowania i jak przetestować, co widzi Google? Przełącz się na zakładkę Zaawansowane.
TL;DR — Problem SEO React nie polega na React — chodzi o domyślne renderowanie po stronie klienta. CRA i Vite + React dostarczają pustą skorupę i budują DOM w przeglądarce, więc surowy HTML pobierany przez crawlera nie zawiera treści. Google może go wyrenderować za pomocą Web Rendering Service (evergreen Chromium), ale renderowanie jest kolejkowane osobno, może być opóźnione i może przekroczyć limit czasu — Gary Illyes udokumentował przekroczenia czasu renderowania pozostawiające strony tylko ze szkieletem, które następnie są oznaczane jako duplikaty. Bing renderuje JS mniej niezawodnie; renderowanie przez AI-crawlerów różni się w zależności od dostawcy. Rozwiązaniem jest strategia renderowania: SSR lub SSG (najłatwiej Next.js lub Remix) umieszcza treść w początkowym HTML — a jeśli hydratujesz renderowany po stronie serwera markup, użyj
hydrateRoot(niecreateRoot) i traktuj każdą niezgodność serwer/klient jako błąd, a nie ostrzeżenie do stłumienia. Następnie użyj routingu History API (nie URL-i z hashem) i prawdziwych linków<a href>. Dla metadanych<head>: React 19 natywnie podnosi<title>/<meta>/<link>; na React 18 lub dla zaawansowanych potrzeb użyj react-helmet-async (nigdy nieutrzymywanego oryginalnego react-helmet). Ustaw poprawne kody statusu HTTP. Nie ma bonusu rankingowego za SSR — po prostu sprawia, że treść jest niezawodnie indeksowalna. Ogólne mechanizmy renderowania znajdziesz w tematach JavaScript SEO i headless CMS.
Co właściwie sprawia, że React jest trudny dla SEO
React to komponentowa biblioteka JavaScript, a po wyjęciu z pudełka — Create React App,
Vite + React — działa po stronie klienta. Serwer zwraca prawie pusty dokument
(słynnie tylko <div id="root"></div>) plus pakiet JavaScript, a przeglądarka
wykonuje ten JavaScript, aby zbudować DOM. Porównaj to z renderowaną po stronie serwera
stroną (WordPress, aplikacja Rails), gdzie pełny HTML — treść, nagłówki, linki —
przychodzi w pierwszej odpowiedzi.
Więc pytanie, które decyduje o wszystkim, brzmi: co jest w surowym HTML, zanim zadziała jakikolwiek JavaScript? Dla domyślnej aplikacji React odpowiedź brzmi „prawie nic”. Kliknij prawym przyciskiem → Pokaż źródło strony w aplikacji CRA i zobaczysz skorupę, a nie treść. Dokładnie to widzi crawler przy pierwszym pobraniu.
Aby być precyzyjnym co do tego, gdzie faktycznie leży odpowiedzialność: sama biblioteka React nie jest
ograniczona do CSR. React DOM dostarcza renderowanie po stronie klienta (createRoot), renderowanie po stronie serwera (strumieniowe
i statyczne API) oraz API hydracji — biblioteka obsługuje to wszystko. Problem pustej skorupy
jest właściwością domyślnego toolchainu (Create React App, Vite + React bez
serwera), który podłącza tylko API klienta i nic, co renderuje HTML na
serwerze. Zmień toolchain — Next.js, Remix lub własne API renderowania po stronie serwera React — i
ta sama biblioteka dostarczy pełny HTML w pierwszej odpowiedzi.
To jest specyficzne dla React zastosowanie szerszego problemu JavaScript SEO — zajrzyj tam po ogólne tryby awarii (parzystość, interakcja, stan, timing). Tutaj skupię się na tym, co jest specyficzne dla React i jak to naprawić.
Jak Google faktycznie przetwarza aplikację React
Google obsługuje JavaScript w trzech fazach: crawl → render → index. Googlebot pobiera URL, a renderowany DOM jest budowany później przez Web Rendering Service (WRS) — wiecznie aktualną wersję Chromium, tego samego silnika co Chrome — a następnie wyrenderowany wynik jest indeksowany i wyodrębniane są z niego linki. Dowód potwierdzający to twierdzenie Google processes JavaScript pages through crawling, rendering, and indexing using its Web Rendering Service. Zakres: Google Search rendering behavior. Poziom ufności: wysoki · Zweryfikowano: Google: JavaScript SEO basics
Ważnym niuansem jest kiedy następuje renderowanie. Renderowanie jest zasobożerne, więc jest kolejkowane osobno od początkowego crawl. Martin Splitt opisał ten proces wprost: “we do an HTTP request, and we get something back … some barebone HTML and all it does is load the JavaScript and run the JavaScript. Then, this HTML … goes into rendering. Rendering runs JavaScript — boom!, a lot of content happens that wasn’t there before.” (tłumaczenie) „wykonujemy żądanie HTTP i dostajemy coś z powrotem … trochę surowego HTML, który robi tylko to, że ładuje JavaScript i uruchamia JavaScript. Potem ten HTML … trafia do renderowania. Renderowanie uruchamia JavaScript — boom!, pojawia się dużo treści, której wcześniej nie było.” Dla strony CSR React „boom” to cała twoja strona — nic z niej nie istnieje, dopóki nie zostanie wykonany ten krok renderowania.
Warto zachować pewną ostrożność: nie przywiązuj się zbytnio do starego modelu „dwóch fal indeksowania”. Sam Splitt się z niego wycofał, nazywając tę falę „uproszczeniem”. Praktyczny wniosek nie brzmi „istnieje formalna Fala 2 z określonym czasem” — chodzi o to, że renderowanie to odrębny, odraczalny i zawodny krok, a CSR umieszcza 100% Twoich treści po złej stronie tego kroku.
Dwa kolejne fakty na temat renderera, które szczególnie dotykają aplikacje React:
- Jest bezstanowy. Googlebot nie przechowuje
localStorage,sessionStorageani plików cookie między kolejnymi wczytaniami stron. Wszelkie treści i routing zależne od stanu po stronie klienta są niewidoczne dla crawlera. - Może się poddać. Renderer egzekwuje limit czasu. Jeśli Twoje główne treści ładują się wolno — duże bundlе, wodospady wywołań API — renderowanie może się zakończyć, zanim Twoje treści dotrą, a Google indeksuje niekompletną stronę.
Pułapka limitu czasu renderowania (i dlaczego tworzy duplikaty)
Ten tryb awarii jest rzadko dobrze wyjaśniany, a dla aplikacji React jest najbardziej szkodliwy. Gary Illyes opisał to wprost: „Mam w skrzynce mnóstwo e-maili, w których problem polega na tym, że główny element ładował się wiecznie, więc renderowanie przekroczyło limit czasu … i zostaliśmy z mnóstwem stron zawierających tylko szablon. Przy samym szablonie te strony są duplikatami.”
Prześledźmy, co to oznacza dla aplikacji CSR React. Twój nagłówek, nawigacja i stopka to szablon, który ładuje się szybko. Twoje właściwe treści strony — część, która czyni każdy URL unikalnym — są pobierane i renderowane przez JavaScript i ładują się wolno. Renderowanie przekracza limit czasu. Google zostaje z nagłówkiem + nawigacją + stopką na każdym URL-u. Teraz każda strona wygląda identycznie, a Google oznacza je jako duplikaty w Search Console.
Własne rozwiązanie Illyesa to praktyczna wskazówka: „Spróbuj przeorganizować wywołania js tak, aby treści (w tym marginalny szablon) ładowały się najpierw i sprawdź, czy to pomoże.” Ale bardziej trwałą odpowiedzią jest niepoleganie na kroku renderowania w przypadku głównych treści — co oznacza SSR lub SSG.
Strategie renderowania dla React
To najważniejsza decyzja. Opcje, z grubsza od najgorszej do najlepszej dla SEO:
- CSR (domyślny React). Serwer wysyła szkielet; przeglądarka buduje wszystko. Treści są opóźnione przez kolejkę renderowania i narażone na limit czasu. Najgorsze dla SEO. Dobre dla uwierzytelnionych pulpitów, których i tak nie chcesz indeksować. Dowód potwierdzający to twierdzenie Client-only React rendering constructs UI in the browser; server rendering APIs produce HTML before browser hydration. Zakres: React rendering mechanics; SEO impact depends on what the initial response contains. Poziom ufności: wysoki · Zweryfikowano: React: hydrateRoot React: Server APIs
- Pre-rendering. Renderowanie w czasie budowy bez pełnego frameworka SSR — narzędzia takie jak
react-snaplub usługa prerenderowania przeszukują Twoją aplikację i zapisują statyczny HTML. Lżejsze; sprawdza się w przypadku prostszych, w większości statycznych witryn. - SSG (Static Site Generation). HTML budowany raz w momencie wdrożenia i serwowany jako pliki statyczne. Najszybsze, treści zawsze obecne w surowym HTML. Ograniczone dla bardzo dynamicznych treści lub treści per użytkownik; duże witryny mają wolne budowanie.
- SSR (Server-Side Rendering). Serwer wykonuje React dla każdego żądania i wysyła pełny HTML. Treści natychmiast dostępne dla crawlerów; zawsze świeże. Wymaga serwera Node.js i nieco wyższego TTFB.
- Hybrydowe / ISR (Incremental Static Regeneration). Funkcja Next.js, która regeneruje statyczne strony w tle — statyczna szybkość z okresową świeżością.
| Strategia | Treści w początkowym HTML? | Ryzyko SEO | Najlepsze dla |
|---|---|---|---|
| CSR (surowy React) | Nie | Najwyższe | Zalogowane pulpity, nieindeksowane aplikacje |
| Pre-rendering | Tak (czas budowy) | Niskie | Małe, w większości statyczne witryny |
| SSG | Tak (czas budowy) | Najniższe | Blogi, dokumentacja, marketing |
| SSR | Tak (na żądanie) | Niskie | Świeże, dynamiczne treści |
| ISR / hybrydowe | Tak | Niskie | Treści zmieniające się co godzinę/dzień |
I jedną strategią, którą warto pominąć przy nowych budowach: renderowanie dynamiczne — wykrywanie user-agenta crawlera i serwowanie mu wstępnie wyrenderowanej wersji, podczas gdy użytkownicy otrzymują CSR. Google nazywa to “a workaround and not a long-term solution” (tłumaczenie) „obejściem, a nie rozwiązaniem długoterminowym”, które “creates additional complexities and resource requirements,” (tłumaczenie) „tworzy dodatkowe komplikacje i wymagania dotyczące zasobów”, i zaleca renderowanie po stronie serwera, renderowanie statyczne lub hydratację zamiast tego. (Bing zalecał renderowanie dynamiczne w 2018 roku, ale te wytyczne są nieaktualne — od 2019 roku Bingbot renderuje przez Microsoft Edge / Chromium, a SSR/SSG jest właściwym rozwiązaniem również tam.)
Warto obalić tutaj pewien mit: SSR nie jest czynnikiem rankingowym. Jak ujął to John Mueller, “there are no SEO ranking bonuses for implementing it one way or another” (tłumaczenie) „nie ma bonusów rankingowych SEO za wdrożenie tego w taki czy inny sposób” — różne metody renderowania to “just different ways of making the content indexable.” (tłumaczenie) „po prostu różne sposoby na uczynienie treści indeksowalną”. Wartość SSR to niezawodna indeksowalność (i często lepsze Core Web Vitals dzięki szybszemu First Contentful Paint), a nie magiczna dźwignia rankingowa.
Hydratacja musi być dokładnie dopasowana — to granica błędów, a nie technika SEO
Zarówno SSR, jak i SSG dostarczają przeglądarce HTML, który już zawiera Twoje treści. React musi następnie podłączyć się do tego znacznika po stronie klienta, a to inne API niż zwykłe renderowanie po stronie klienta:
createRootrenderuje React do węzła DOM od zera — bez oczekiwania na istniejący znacznik. Użyj go w aplikacjach tylko z CSR.hydrateRootpodłącza React do HTML, który już wygenerowałreact-dom/server, i oczekuje, że pierwsze renderowanie po stronie klienta da wynik identyczny z tym, co wysłał serwer. Jeśli używasz SSR/SSG, potrzebujeszhydrateRoot, a niecreateRoot— wywołaniecreateRootna znaczniku wyrenderowanym po stronie serwera powoduje, że React go odrzuca i renderuje od zera, marnując dokładnie tę korzyść SEO, dla której skonfigurowałeś SSR/SSG.
Niezgodności między wynikiem serwera a klienta to realne ryzyko w aplikacjach React wykonujących poprawki SEO — Date.now() w tytule, format zależny od locale, gałąź if (typeof window !== 'undefined'). Dokumentacja Reacta jest wprost szczera co do tego, co się wtedy dzieje: ostrzega o niezgodnościach w trybie deweloperskim, ale “there are no guarantees that attribute differences will be patched up in case of mismatches.” (tłumaczenie) „nie ma gwarancji, że różnice atrybutów zostaną poprawione w przypadku niezgodności”. Zalecenie to traktować niezgodności jako błędy i je naprawiać — a nie tłumić ostrzeżenie i zakładać parytet treści. W kontekście SEO: nie zakładaj, że wyrenderowane treści i metadane są zgodne z tym, co wysłał serwer, tylko dlatego, że strona wygląda dobrze w przeglądarce. Porównaj bezpośrednio HTML serwera z DOM po hydratacji (szybka wersja tego to sprawdzenie źródła strony i elementu w inspektorze z sekcji testowania poniżej), zamiast ufać czystej konsoli.
React Router i struktura URL
React Router obsługuje nawigację w przeglądarce bez rund do serwera, co jest w porządku dla SEO jeśli jest poprawnie skonfigurowany:
- Użyj History API, a nie routingu hash.
BrowserRouterużywapushStatei generuje czyste, indeksowalne URL-e (/products).HashRoutergeneruje/#/products, a Google nie może niezawodnie rozwiązywać URL-i opartych na hashu — stary schemat indeksowania AJAX, który je obsługiwał, jest przestarzały. Użyj History API. - Serwer musi również obsługiwać te URL-e. Przy routingu z History API każda “strona” potrzebuje prawdziwego URL-a, na który serwer może odpowiedzieć — to kluczowe dla SSR i konieczne, aby bezpośrednie wejście lub odświeżenie na
/productsnie zwracało 404. <Link>renderuje prawdziwy kotwicę. Komponent<Link>z React Routera wyprowadza<a href>, który jest indeksowalny. Nawigacja zbudowana na handlerachonClickbez kotwicy nie jest indeksowalna — Google podąża tylko za prawdziwymi linkami<a href>.
Zarządzanie metadanymi: react-helmet, react-helmet-async i natywne tagi React 19
W React 18, React nigdy natywnie nie aktualizował <head> dokumentu przy zmianach tras —
każdy <title>, meta description, canonical oraz tagi Open Graph / Twitter musiały być
ustawiane przez bibliotekę. React 19 to zmienił: komponenty mogą renderować tagi <title>,
<meta> i <link> bezpośrednio, a React sam przenosi je do <head> —
działa to zarówno w aplikacjach client-only, streamingowym SSR, jak i Server Components. React 19.2 to
obecna stabilna wersja na połowę 2026 roku, więc dotyczy to teraz każdej aplikacji na aktualnej
wersji Reacta.
Oznacza to, że właściwa odpowiedź zależy od Twojej wersji Reacta i tego, czego faktycznie potrzebujesz:
- React 19, samodzielna aplikacja, tylko podstawowe tagi. Renderuj
<title>/<meta>/<link>bezpośrednio w komponentach — żadna biblioteka nie jest potrzebna. - React 19, ale potrzebujesz
htmlAttributes/bodyAttributes, serializacjicontextw SSR,onChangeClientState,prioritizeSeoTagslubtitleTemplate. Natywne przenoszenie tagów tego nie obejmuje — użyjreact-helmet-async. Jego dokumentacja wprost to podkreśla: bez tych konkretnych potrzeb możesz w ogóle nie potrzebować tego pakietu w React 19. - React 18 lub starszy, samodzielna aplikacja. Natywne przenoszenie tagów jeszcze nie istnieje —
użyj
react-helmet-async. Jest aktywnie utrzymywany (wersja główna 3, a wykrywa Twoją wersję Reacta w czasie działania) i obsługuje SSR. - Oryginalny
react-helmet. Nie używaj go w żadnej wersji Reacta. Jest nieutrzymywany — brak wydań od 2020 roku — i ma znane błędy przy renderowaniu współbieżnym w React 18. - Aplikacje Next.js. Użyj własnego API Metadata w Next (eksport
metadata/generateMetadataw App Router) niezależnie od wersji Reacta — nie dokładaj Helmeta i nie polegaj też na natywnym przenoszeniu tagów przez Reacta. Framework zarządza dokumentem w aplikacji Next.js.
Jedna zasada niezawodności przenosi się z JavaScript SEO ogólnie i obowiązuje niezależnie od tego, którego z powyższych używasz: metadane na poziomie HTML biją metadane wstrzykiwane przez JS. Tag canonical wstrzyknięty przez JavaScript po stronie klienta jest znacznie mniej niezawodny niż ten obecny w HTML renderowanym po stronie serwera — co jest kolejnym argumentem za SSR/SSG.
Boty AI sprawiają, że to pilne
Zawiłość roku 2026: zachowanie renderowania dla GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot i innych agentów zależy od dostawcy i wersji. Aplikacja CSR w React wysyła każdemu botowi tę samą pustą skorupę, którą widzi pierwsze pobranie Googlebota, a obecna dokumentacja dostawców nie ustala jednego wspólnego kroku renderowania, który by ją wypełnił. W miarę jak silniki generatywne stają się większą powierzchnią odkrywania, SSR/SSG przestaje być problemem tylko Google: surowy HTML maksymalizuje zasięg bez zakładania uniwersalnego ograniczenia botów. (Temat headless CMS omawia tę rzeczywistość botów AI bardziej szczegółowo.)
Testowanie tego, co faktycznie widzi Google
Nie ufaj swojej przeglądarce — Inspektor w DevTools pokazuje wyrenderowany DOM (po JavaScript), czyli dokładnie to, czego bot bez JS nie widzi. Użyj właściwych narzędzi:
- View Source vs. Inspect Element. View Source to surowy HTML (to, co boty dostają przed JS). Inspect Element to wyrenderowany DOM. Jeśli treść jest w Inspect, ale brakuje jej w View Source, jest zależna od JavaScriptu.
- URL Inspection Tool (Search Console) — najbardziej autorytatywna kontrola. Uruchom test na żywo i sprawdź wyrenderowany HTML, zrzut ekranu oraz zasoby strony / komunikaty konsoli, aby zobaczyć, co Google faktycznie wyrenderował i co nie zostało załadowane.
- Rich Results Test — szybka kontrola wyrenderowanego HTML bez weryfikacji strony.
- Wyłącz JavaScript w DevTools i przeładuj — szybka symulacja bota, który nie wykonuje JS (i niezły przybliżony odpowiednik tego, co widzą boty AI).
- Raport pokrycia w Search Console — „Discovered, currently not indexed” może sygnalizować zaległości w kolejce renderowania; klastry zduplikowanych stron mogą sygnalizować pułapkę boilerplate przy przekroczeniu limitu czasu renderowania.
- Boty renderujące JS — Ahrefs Site Audit i Screaming Frog (tryb renderowania JS) renderują strony na dużą skalę, dzięki czemu możesz porównać surowy i wyrenderowany HTML w całej witrynie.
Next.js i Remix (praktyczna odpowiedź)
Jeśli SEO ma znaczenie i używasz czystego CSR React, migracja do frameworka renderującego po stronie serwera jest zwykle właściwym krokiem. Next.js jest do tego stworzony — SSR i SSG od razu po wyjęciu z pudełka, ISR, App Router, wbudowane Metadata API, automatyczne dzielenie kodu i optymalizacja obrazów. Remix to alternatywa oparta na standardach internetowych, zbudowana na fetch/Request/Response z SSR domyślnie i mocnym naciskiem na progresywne ulepszanie. Next.js doczeka się osobnego, dogłębnego omówienia — celowo trzymam się tu krótko. Sedno dla SEO Reacta jest węższe: framework istnieje po to, aby przenieść Twoje treści z etapu renderowania tylko w przeglądarce do początkowego HTML.
React jest dobry dla SEO, gdy traktujesz renderowanie jako decyzję architektoniczną, a nie coś dodatkowego. Wybierz SSR lub SSG dla wszystkiego, co ma się pozycjonować, dbaj o uczciwe linki i routing, zarządzaj metadanymi dla każdej trasy i pozwól narzędziom Google — a nie swojej przeglądarce — powiedzieć Ci, co faktycznie zostało wyrenderowane.
Podsumowanie AI
Skrócona wersja wersji zaawansowanej:
- React nie jest zły dla SEO — domyślny CSR jest. Biblioteka React wspiera renderowanie po stronie klienta, serwera, statyczne i strumieniowe; to domyślny toolchain CRA/Vite (bez serwera) wysyła pusty
<div id="root">i buduje DOM w przeglądarce, więc surowy HTML pobierany przez crawlera nie ma treści. - Google potrafi renderować React przez Web Rendering Service (evergreen Chromium), ale renderowanie jest kolejkowane osobno, może być opóźnione i jest bezstanowe (brak cookies/localStorage/sessionStorage między ładowaniami).
- Pułapka limitu czasu renderowania: jeśli główna treść ładuje się wolno, renderowanie przekracza limit czasu i Google indeksuje stronę tylko ze szkieletem. W przypadku wielu adresów URL wyglądają one identycznie i są oznaczane jako duplikaty (udokumentowany tryb awarii Gary’ego Illyesa). Rozwiązanie: najpierw załaduj treść — albo lepiej, nie polegaj na kroku renderowania (SSR/SSG).
- Strategie renderowania, najlepsze→najgorsze dla SEO: SSG (najniższe ryzyko) ≈ SSR ≈ pre-render > ISR/hybrydowe > CSR (najwyższe ryzyko). Dynamiczne renderowanie jest przestarzałe — Google zaleca SSR, renderowanie statyczne lub hydratację.
- Brak bonusu rankingowego za SSR — Mueller: “no SEO ranking bonuses for implementing it one way or another.” (tłumaczenie) „Brak bonusów rankingowych SEO za wdrożenie tego w taki czy inny sposób.” To po prostu sprawia, że treść jest niezawodnie indeksowalna.
- Hydratacja to granica błędów, a nie technika: aplikacje SSR/SSG hydratują za pomocą
hydrateRoot(niecreateRoot), co wymaga, aby pierwsze renderowanie po stronie klienta dokładnie odpowiadało temu po stronie serwera. React ostrzega o niezgodnościach w trybie deweloperskim, ale nie gwarantuje ich naprawy — traktuj niezgodności jako błędy i weryfikuj bezpośrednio DOM serwera vs. po hydratacji. - React Router: używaj History API (
BrowserRouter), a nie routingu hash; serwer musi obsługiwać te adresy URL;<Link>renderuje indeksowalny<a href>— nawigacja tylko przezonClicknie. - Metadane: React 19 natywnie przenosi
<title>/<meta>/<link>do<head>dla samodzielnych aplikacji potrzebujących tylko podstaw. W React 18 lub dla zaawansowanych potrzeb (kontekst SSR,titleTemplate) użyj react-helmet-async — nigdy oryginalnego react-helmet, nieutrzymywanego od 2020. W Next.js użyj Metadata API niezależnie od wersji Reacta. Poziom HTML jest lepszy niż wstrzykiwany przez JS. - Renderowanie przez crawlerów AI zależy od dostawcy — CSR React polega na wykonaniu po stronie klienta, które każdy crawler może wspierać lub nie. SSR/SSG umieszcza treść w początkowym HTML i maksymalizuje zasięg.
- Testuj za pomocą View Source vs. Inspect, URL Inspection (wyrenderowany HTML + zrzut ekranu + konsola), Rich Results Test, przeładowania z wyłączonym JS i crawlera renderującego JS.
- Next.js / Remix to praktyczne rozwiązanie — przenoszą treść do początkowego HTML.
Oficjalna dokumentacja
Dokumentacja źródłowa od wyszukiwarek.
- Podstawy SEO dla JavaScriptu — potok pobieranie → renderowanie → indeksowanie, aplikacje SPA, interfejs History API, kanoniczne adresy URL w JS i prawidłowe kody statusu HTTP.
- Rozwiązywanie problemów z JavaScriptem w wyszukiwarce — obsługa miękkich błędów 404 w SPA, bezstanowy renderer bez plików cookie i pamięci lokalnej oraz testowanie przez sprawdzanie adresu URL.
- Renderowanie dynamiczne — przestarzałe obejście — dlaczego Google je wycofało i czego używać zamiast niego: SSR, renderowania statycznego lub hydratacji.
- Nowa seria filmów o SEO dla JavaScriptu — seria Martina Splitta poświęcona między innymi Reactowi, Angularowi i Vue.
- Szczegółowy przewodnik po działaniu wyszukiwarki Google — miejsce renderowania w potoku pobieranie → indeksowanie → udostępnianie.
Bing / Microsoft
- Nowy, stale aktualizowany Bingbot oparty na Microsoft Edge — Bingbot renderujący JavaScript na tej samej platformie Chromium co Googlebot.
- Seria o Bingbocie: JavaScript, renderowanie dynamiczne i cloaking — starsze stanowisko Bing z 2018 roku, przydatne jako historyczny kontekst zaleceń dotyczących renderowania dynamicznego.
Dokumentacja techniczna
- React 19 — informacje o wydaniu — natywna obsługa renderowania znaczników
<title>,<meta>i<link>w komponentach oraz ich automatycznego przenoszenia do<head>. - createRoot / hydrateRoot (dokumentacja Reacta) — podział interfejsów renderowania po stronie klienta i hydratacji oraz zastrzeżenie, że poprawienie niezgodności nie jest gwarantowane.
- react-helmet-async w npm — utrzymywany fork do zarządzania
<head>w samodzielnych aplikacjach React, potrzebny w React 18 i niektórych zaawansowanych przypadkach React 19.
Cytaty ze źródła
Oficjalne wypowiedzi zespołu wyszukiwarki Google. Każdy link prowadzi bezpośrednio do cytowanego fragmentu strony źródłowej; wypowiedzi pracowników mają odsyłacze do relacji, które je przytoczyły.
Dokumentacja Google — aplikacje SPA i renderowanie dynamiczne
- “Single-page applications (SPA) are websites that load an HTML document once and fetch any additional content using JavaScript APIs.” (tłumaczenie) „Aplikacje jednostronicowe (SPA) to witryny, które wczytują dokument HTML raz, a wszelką dodatkową treść pobierają przez interfejsy API JavaScriptu.” — dokumentacja Google Search Central. Przejdź do cytatu
- “Dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” (tłumaczenie) „Renderowanie dynamiczne było obejściem, a nie długoterminowym rozwiązaniem problemów z treścią generowaną przez JavaScript w wyszukiwarkach.” — dokumentacja Google Search Central. Przejdź do cytatu
Martin Splitt, Google — sposób indeksowania stron korzystających z JavaScriptu
- “What we do is we do an HTTP request, and we get something back, right — some HTML, maybe it’s a barebone HTML and all it does is load the JavaScript and run the JavaScript. Then, this HTML that we got from the original HTTP GET request from the crawl, goes into rendering. Rendering runs JavaScript — boom!, a lot of content happens that wasn’t there before.” (tłumaczenie) «Robimy żądanie HTTP i dostajemy coś z powrotem, prawda — jakiś HTML, może to być goły HTML, który tylko ładuje JavaScript i go uruchamia. Potem ten HTML, który otrzymaliśmy z oryginalnego żądania HTTP GET z crawlowania, trafia do renderowania. Renderowanie uruchamia JavaScript — boom!, pojawia się dużo treści, której wcześniej nie było.» Przeczytaj relację (Search Engine Journal)
- O tym, że model dwóch fal jest nieprecyzyjny: “there’s no such thing as the second wave of crawling-ish. The wave is an oversimplification.” (tłumaczenie) «Nie ma czegoś takiego jak druga fala crawlowania. Fala to uproszczenie.» Przeczytaj relację (Search Engine Roundtable)
Gary Illyes, Google — pułapka duplikatów treści z powodu przekroczenia limitu czasu renderowania
- “I have a bunch of emails in my inbox where the issue is that the centerpiece took forever to load, so rendering timed out (my most likely explanation) and we were left with a bunch of pages that only had the boilerplate. With only the boilerplate, those pages are dups.” (tłumaczenie) «Mam w skrzynce mnóstwo e-maili, w których problem polega na tym, że główna treść ładowała się wiecznie, więc renderowanie przekroczyło limit czasu (moje najbardziej prawdopodobne wyjaśnienie) i zostaliśmy z wieloma stronami, które miały tylko szablon. Mając tylko szablon, te strony są duplikatami.»
- “Do you have a JavaScript-heavy site and you see lots of dups reported in Search Console? Try to restructure the js calls such that the content (including marginal boilerplate) loads first and see if that helps.” (tłumaczenie) «Czy masz stronę opartą na JavaScript i widzisz wiele duplikatów zgłaszanych w Search Console? Spróbuj przeorganizować wywołania JS tak, aby treść (w tym marginalny szablon) ładowała się najpierw i sprawdź, czy to pomoże.» Przeczytaj post (LinkedIn)
John Mueller, Google — brak bonusu rankingowego za wybór renderowania
- “There are no SEO ranking bonuses for implementing it one way or another.” (tłumaczenie) „Nie ma bonusów rankingowych SEO za wdrożenie tego w taki czy inny sposób.” To “just different ways of making the content indexable (as is client side rendering).” (tłumaczenie) „Po prostu różne sposoby na uczynienie treści indeksowalną, podobnie jak renderowanie po stronie klienta.” Przeczytaj relację (Search Engine Roundtable)
Lista kontrolna SEO dla React
Przegląd, aby potwierdzić, że crawlerzy mogą zobaczyć i zaindeksować Twoją aplikację React:
- Ważna treść pojawia się w View Source (surowy HTML), nie tylko w renderowanym DOM — jeśli jej brakuje, polegasz na CSR.
- Strony, które mają się pozycjonować, używają SSR lub SSG (Next.js, Remix lub krok pre-renderowania), nie surowego renderowania po stronie klienta.
- Główna treść ładuje się szybko i jako pierwsza — bez wolnych wodospadów API, które mogłyby przekroczyć limit czasu renderowania i dać stronę tylko ze szkieletem.
- Routing używa History API (
BrowserRouter), nieHashRouter/ adresów#/. - Serwer może odpowiedzieć na każdą trasę po stronie klienta (bez błędu 404 przy bezpośrednim wejściu lub odświeżeniu).
- Nawigacja używa prawdziwych linków
<a href>(React Router<Link>), nie tylko handlerówonClickna<div>/<button>. - Każda trasa ustawia unikalny
<title>, meta description, canonical i tagi OG, które aktualizują się przy nawigacji. - Metadane odpowiadają Twojej wersji: React 19 natywne tagi
<title>/<meta>/<link>dla podstaw, react-helmet-async dla React 18 lub zaawansowanych potrzeb (nigdy przestarzałyreact-helmet), lub Next.js Metadata API, jeśli używasz Next.js. - Jeśli renderowane po stronie serwera, hydratacja odbywa się przez
hydrateRoot(niecreateRoot), a ostrzeżenie o niezgodności hydratacji w trybie deweloperskim traktujesz jako błąd do naprawy. - Trasy „nie znaleziono” po stronie klienta zwracają prawdziwy 404 (lub
noindex), nie miękki 404 ze statusem200. - JavaScript i CSS nie są blokowane w
robots.txt(Google nie renderuje z zablokowanych plików). - Żadna krytyczna treść nie zależy od cookies / localStorage / sessionStorage (renderer jest bezstanowy).
- Zweryfikowano w URL Inspection: wyrenderowany HTML i zrzut ekranu pokazują Twoją prawdziwą treść.
- Sprawdzono raport pokrycia pod kątem „Discovered, currently not indexed” (zaległości w renderowaniu) i duplikatów klastrów (pułapka przekroczenia limitu czasu renderowania).
Modele mentalne
1. Jedyne pytanie, które się liczy: co jest w surowym HTML? View Source przed uruchomieniem jakiegokolwiek JavaScriptu to to, co widzi robot przy pierwszym pobraniu — i większość robotów AI, zawsze. Jeśli Twojej treści tam nie ma, masz problem z SEO w React, niezależnie od tego, jak dobrze strona wygląda w przeglądarce.
2. Renderowanie to osobny, zawodny krok. Crawl → render → index. CSR umieszcza 100% Twojej treści po drugiej stronie kroku renderowania, który jest w kolejce, opóźniony, bezstanowy i może przekroczyć limit czasu. SSR/SSG przenoszą Twoją treść przed ten krok. Nie ufaj zbytnio modelowi „dwóch fal” — sam Splitt nazwał go uproszczeniem.
3. Tryb awarii: duplikaty szablonu. Wolna treść + przekroczenie limitu czasu renderowania = każdy URL renderuje się tylko jako nagłówek/nawigacja/stopka = Google widzi duplikaty. Rozwiązanie jest strukturalne: ładuj treść najpierw albo przestań polegać na kroku renderowania.
4. Drzewo decyzyjne renderowania.
- Treść publiczna, która musi się pozycjonować lub być cytowana przez AI → SSG (statyczna) lub SSR (świeża).
- Głównie statyczna (blog, dokumentacja, marketing) → SSG, lub ISR z timerem.
- Często zmieniająca się, musi być świeża → SSR.
- Panel zalogowanego użytkownika, nieprzeznaczony do indeksowania → CSR jest w porządku.
- Nowa budowa, która potrzebuje SEO → sięgnij po Next.js / Remix, nie dynamiczne renderowanie.
5. HTML najpierw, JS drugi dla każdego sygnału SEO. Treść, linki, kanoniki, tytuły, dane strukturalne — umieść je w HTML renderowanym po stronie serwera. Traktuj sygnały SEO wstrzykiwane przez JS (w tym kanoniczne tagi JS i react-helmet w CSR) jako fallback, nie plan: Google widzi je późno, a roboty AI wcale.
React SEO — ściągawka
Tryby renderowania w skrócie
| Tryb | Treść w początkowym HTML? | Ryzyko SEO | Użyj do |
|---|---|---|---|
| CSR (surowy React) | Nie | Najwyższe | Panele zalogowanych użytkowników, aplikacje nieindeksowane |
| Pre-renderowanie (react-snap) | Tak (czas budowy) | Niskie | Małe, głównie statyczne strony |
| SSG | Tak (czas budowy) | Najniższe | Blogi, dokumentacja, marketing |
| SSR | Tak (na żądanie) | Niskie | Świeża, dynamiczna treść |
| ISR / hybrydowe (Next.js) | Tak | Niskie | Treść aktualizowana co godzinę/dzień |
| Dynamiczne renderowanie | Tylko dla botów | Przestarzałe | Nie używaj — użyj SSR/SSG/hydratacji |
Częste błędy SEO w React → poprawki
| Błąd | Poprawka |
|---|---|
| Treść tylko w renderowanym DOM (CSR) | SSR / SSG / pre-render |
Hash URL (/#/path) | History API (BrowserRouter) |
Nawigacja onClick, brak kotwicy | Prawdziwy <a href> / React Router <Link> |
| Meta tagi nie aktualizują się przy zmianie trasy | React 19: natywne <title>/<meta>/<link>. Starsze/zaawansowane: react-helmet-async. Next.js: Metadata API |
react-helmet (oryginalny, dowolna wersja React) | Przejdź na react-helmet-async lub natywne tagi React 19 |
createRoot użyty na serwerowo renderowanym HTML | Użyj hydrateRoot zamiast — createRoot odrzuca znaczniki serwera |
| Ostrzeżenie o niezgodności hydratacji zignorowane | Traktuj to jako błąd i napraw różnicę serwer/klient |
| Wolna treść → przekroczenie limitu renderowania → duplikaty | Załaduj główną treść najpierw; przejdź na SSR/SSG |
Błąd 404 po stronie klienta zwraca 200 | Prawdziwy status 404 lub noindex |
Zablokowane .js / .css w robots.txt | Zezwól na nie — Google nie renderuje zablokowanych plików |
| Treść ograniczona przez cookies/localStorage | Nie rób tego — renderer jest bezstanowy |
Szybkie zasady
- Renderer to evergreen Chromium, w kolejce, bezstanowy i z limitem czasu.
- Brak bonusu rankingowego dla SSR — chodzi o niezawodną indeksowalność (Mueller).
- Renderowanie przez AI-crawlerów różni się w zależności od dostawcy → surowy HTML to najbezpieczniejsza podstawa pokrycia.
- W Next.js używaj Metadata API — nie React Helmet.
- Bing renderuje JS (przez Edge), ale mniej niezawodnie; SSR/SSG to bezpieczne rozwiązanie również tam.
Sprawdź, co serwer wysyła, zanim React uruchomi się
Umieść reprezentatywne indeksowalne trasy w urls.txt. To wykrywa CSR-shell i brakujący
serwerowo renderowany head w surowej odpowiedzi:
while IFS= read -r url; do
html=$(mktemp)
status=$(curl -sS -o "$html" -w '%{http_code}' "$url")
bytes=$(wc -c < "$html" | tr -d ' ')
title_count=$(grep -Eio '<title>[^<]*</title>' "$html" | wc -l | tr -d ' ')
canonical_count=$(grep -Eio '<link[^>]+rel=["'"']canonical["'"'][^>]*>' "$html" | wc -l | tr -d ' ')
printf '%s\t%s\tbytes=%s\ttitles=%s\tcanonicals=%s\n' "$status" "$url" "$bytes" "$title_count" "$canonical_count"
rm -f "$html"
done < urls.txtMały rozmiar bajtów to tylko sygnał do przeglądu, nie błąd sam w sobie. Porównaj oznaczone surowe odpowiedzi z renderowanym HTML i potwierdź, że główny tekst i linki do przeszukania są obecne.
Narzędzia do audytu SEO React
- View Source vs. Inspect Element — najszybsza pierwsza kontrola. View Source to surowy HTML (to, co crawler otrzymuje przed JS); Inspect Element to renderowany DOM. Treść w Inspect, ale nie w View Source, zależy od JavaScript.
- URL Inspection (Google Search Console) — źródło prawdy. Uruchom test na żywo, a następnie zobacz renderowany HTML, zrzut ekranu, zasoby strony (co się załadowało vs. co było zablokowane) oraz komunikaty konsoli, aby zobaczyć dokładnie, co Google wyrenderował.
- Rich Results Test — szybka kontrola renderowanego HTML i danych strukturalnych dla pojedynczego URL bez weryfikacji witryny.
- Chrome DevTools — wyłącz JavaScript (Menu poleceń → “Disable JavaScript”) i przeładuj, aby sprawdzić, co otrzymuje fetcher tylko-HTML. To kontrola pokrycia, nie dowód na obecne zachowanie renderowania żadnego nazwanego AI-crawlera.
- Search Console Coverage report — obserwuj “Discovered, currently not indexed” (kolejka renderowania) i klastry duplikatów (pułapka boilerplate przy przekroczeniu limitu renderowania).
- Crawler-y renderujące JS — Ahrefs Site Audit i Screaming Frog SEO Spider (tryb renderowania JS) wykonują JavaScript, więc możesz porównać surowy vs. renderowany HTML w całej witrynie.
Błędy, które zespoły React faktycznie popełniają
Konkretne wzorce, które ciągle widzę w CSR React aplikacjach wysyłanych do produkcji, nie hipotetyczne. Każdy to ruch zapobiegawczy — złap to, zanim kosztuje Cię indeksowanie.
Wysyłanie surowego CRA/Vite CSR dla stron, które mają rankować
Zespoły wysyłają Create React App lub Vite + React bezpośrednio do produkcji dla stron marketingowych,
postów na blogu lub stron produktowych — dokładnie tej treści, która musi pojawić się w wyszukiwarce.
Dlaczego to błąd: serwer wysyła prawie pusty <div id="root"> shell; Twoja prawdziwa
treść istnieje tylko po uruchomieniu JavaScript, więc jest opóźniona przez kolejkę renderowania Google i
może być niewidoczna dla każdego AI-crawlera, który pobiera początkowy HTML bez wykonania klienta.
Co zamiast tego: przenieś
wszystko, co musi rankować lub być cytowane, do SSR lub SSG — Next.js lub Remix to najłatwiejsze
ścieżki — i zarezerwuj surowy CSR dla zalogowanych, nieindeksowanych powierzchni, takich jak dashboardy.
Routing na hash URL (HashRouter)
Sięganie po HashRouter z React Router, bo to ścieżka najmniejszego oporu —
nie wymaga konfiguracji serwera, działa na każdym statycznym hostingu. Dlaczego to błąd: Google nie może
niezawodnie rozwiązać adresów URL w stylu /#/products; stary schemat indeksowania AJAX, który umożliwiał
indeksowanie fragmentów hashy, jest przestarzały. Co zamiast tego: użyj BrowserRouter (API
History) i upewnij się, że serwer odpowiada na każdą wygenerowaną przez niego trasę, w tym na
bezpośrednie wejście lub odświeżenie na głębokim linku.
Budowanie nawigacji na onClick zamiast prawdziwych kotwic
Podpinanie nawigacji za pomocą handlerów onClick na <div> lub <button>, często dlatego, że
łatwiej było je stylizować lub uniknąć domyślnego zachowania linków. Dlaczego to błąd: Google
podąża tylko za prawdziwymi linkami <a href> — <div> z handlerem kliknięcia jest niewidoczny dla
crawlującego, niezależnie od tego, jak zachowuje się dla myszy. Co zamiast tego: użyj komponentu
<Link> z React Router, który renderuje prawdziwy <a href> pod spodem, lub zwykłego znacznika kotwicy
dla zewnętrznej nawigacji.
Ładowanie głównej treści za wolnym wodospadem API
Szybkie pobieranie nagłówka i nawigacji, a następnie łączenie kilku wywołań API, zanim pojawi się właściwa treść strony — ta część, która czyni każdy URL unikalnym. Dlaczego to błąd: usługa renderowania Google egzekwuje limit czasu; jeśli Twoja główna treść ładuje się wolno, renderowanie kończy się, zanim dotrze, a Google pozostaje z indeksowaniem stron zawierających tylko boilerplate, które następnie są oznaczane jako duplikaty siebie nawzajem — dokładnie ten tryb awarii, który opisał Gary Illyes. Co zamiast tego: przeorganizuj żądania tak, aby główna treść ładowała się najpierw, lub całkowicie usuń zależność od renderowania po stronie klienta dzięki SSR/SSG.
Nadal używanie oryginalnego react-helmet
Sięganie po react-helmet dla per-route <title> i tagów meta, ponieważ to
biblioteka, którą poleca każdy starszy tutorial. Dlaczego to błąd: oryginalny pakiet jest
nieutrzymywany — brak wydań od 2020 roku — i ma znane problemy z renderowaniem współbieżnym React 18
i SSR. Co zamiast tego: w React 19 renderuj <title>/<meta>/<link>
bezpośrednio w komponentach i pozwól Reactowi je podnieść (do podstaw nie potrzebujesz biblioteki).
W React 18 lub w przypadku zaawansowanych potrzeb, takich jak serializacja kontekstu SSR lub titleTemplate, użyj
react-helmet-async, utrzymywanego forka. W Next.js użyj wbudowanego API Metadata i
nie dokładaj Helmeta na to.
Blokowanie JavaScript lub CSS w robots.txt
Blokowanie /static/js/ lub folderu zasobów bundlera w robots.txt, czasem pozostałość
po starym problemie z budżetem crawlującym lub skopiowane z konfiguracji innej witryny. Dlaczego to
błąd: Google nie może renderować tego, czego nie wolno mu pobrać — zablokowany bundle oznacza, że
usługa renderowania buduje niekompletny (lub pusty) DOM, nawet jeśli Twój kod źródłowy jest
w porządku. Co zamiast tego: pozwól crawlerom pobierać Twój JS i CSS i potwierdź to
za pomocą narzędzia URL Inspection w sekcji zasobów strony, aby zobaczyć, że nic krytycznego nie jest zablokowane.
Sprawdź się: React SEO
Pięć szybkich pytań o to, jak uczynić aplikacje React crawlującymi i indeksowalnymi. Wybierz odpowiedź na każde, a następnie sprawdź.
Zasoby warte Twojego czasu
Moje powiązane artykuły
- SEO dla Reacta: dobre praktyki przyjaznej optymalizacji (Ahrefs) — przewodnik po React SEO na Ahrefs, który recenzowałem; ten artykuł to głębsze, oparte na źródłach opracowanie.
- SEO dla JavaScriptu: kompletny przewodnik (Ahrefs) — mój pełny przewodnik po podstawowych mechanizmach renderowania: parytet DOM, zasada najbardziej restrykcyjnej dyrektywy, obsługa kanonicznych i tagów meta oraz wybory renderowania. Przeczytaj to, aby poznać ogólny przypadek stojący za poprawkami specyficznymi dla React.
- Przewodnik dla początkujących po technicznym SEO (Ahrefs) — gdzie React/JavaScript SEO wpisuje się w szerszy obraz.
Moje wystąpienia
- Jak działa wyszukiwarka (SlideShare) — moje omówienie pobierania, renderowania, indeksowania i rankingu. (Moje stałe zastrzeżenie: “This is my understanding of systems… not going to be 100% complete or accurate.” (tłumaczenie) „To moje rozumienie systemów… nie będzie w 100% kompletne ani dokładne.”)
Z branży
- Podstawy SEO dla JavaScriptu (Google) — dokumentacja źródłowa na temat SPA, History API oraz obsługi adresów kanonicznych i kodów statusu.
- Renderowanie dynamiczne — przestarzałe (Google) — dlaczego renderowanie dynamiczne to obejście, a nie długoterminowe rozwiązanie.
- Martin Splitt wyjaśnia, jak indeksowane są witryny JavaScript (Search Engine Journal) — wyjaśnienie dotyczące procesu pobieranie → renderowanie → indeksowanie.
- Gary Illyes o witrynach intensywnie korzystających z JS i duplikatach treści (LinkedIn) — scenariusz awarii od przekroczenia limitu renderowania do duplikatów, jego własnymi słowami.
- Jak naprawiać techniczne problemy SEO w aplikacjach React renderowanych po stronie klienta (Search Engine Land) — studium przypadku z audytu i naprawy aplikacji React CSR.
- SSR a renderowanie dynamiczne — brak różnicy rankingowej (Search Engine Roundtable) — stwierdzenie Muellera o braku bonusów rankingowych.
- react-helmet-async (npm) — utrzymywana biblioteka do zarządzania head dla samodzielnego Reacta.
- Nowy, stale aktualizowany Bingbot oparty na Microsoft Edge (Bing) — Bingbot renderujący JS przez Chromium, podobnie jak Googlebot.
Filmy
- Google Search Central — JavaScript SEO series (YouTube) — oficjalna seria wideo Martina Splitta obejmuje SEO dla React, Angular i Vue, przeprowadzając przez proces crawl → render → index oraz typowe poprawki. Ogłoszenie serii · Kanał
Dziennik zmian
Zaktualizowano 18 lip 2026.
Podsumowanie redakcyjne i zapisane szczegóły zmian.Szczegóły zmian
-
Szczegółowe uwagi dotyczące zmian są obecnie dostępne po angielsku.
-
Szczegółowe uwagi dotyczące zmian są obecnie dostępne po angielsku.
-
Szczegółowe uwagi dotyczące zmian są obecnie dostępne po angielsku.
Pełne porównanie jest niedostępne — dla tej wersji nie zarchiwizowano wcześniejszej migawki.