{"id":2391,"date":"2024-12-09T13:29:00","date_gmt":"2024-12-09T12:29:00","guid":{"rendered":"https:\/\/jalvo.eu\/javascript-seo-jak-googlebot-pobiera-i-renderuje-zasoby\/"},"modified":"2024-12-09T13:29:00","modified_gmt":"2024-12-09T12:29:00","slug":"javascript-seo-jak-googlebot-pobiera-i-renderuje-zasoby","status":"publish","type":"post","link":"https:\/\/jalvo.eu\/pl\/javascript-seo-jak-googlebot-pobiera-i-renderuje-zasoby\/","title":{"rendered":"JavaScript SEO: jak Googlebot pobiera i renderuje zasoby"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Googlebot najpierw pobiera HTML nadrz\u0119dnego adresu URL. Potem Web Rendering Service pobiera pliki JavaScript i CSS, na kt\u00f3re wskazuje ten kod, i buduje stron\u0119 tak, jak zrobi\u0142aby to przegl\u0105darka. A tekst, kt\u00f3ry pojawia si\u0119 dopiero po tym kroku? Trafia do indeksu tylko wtedy, gdy ka\u017cdy wymagany zas\u00f3b jest dost\u0119pny. To JavaScript SEO w pigu\u0142ce i zarazem wyja\u015bnienie objawu, kt\u00f3ry wi\u0119kszo\u015b\u0107 z nas ju\u017c widzia\u0142a: w przegl\u0105darce strona wygl\u0105da na kompletn\u0105, a Google pokazuje ledwie skrawek jej tekstu. Temat jest te\u017c \u015bwie\u017cy, bo 3 grudnia 2024 Google otworzy\u0142 seri\u0119 Crawling December wpisem o pobieraniu zasob\u00f3w i bud\u017cecie indeksowania.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Jak Googlebot pobiera stron\u0119 opart\u0105 na JavaScript?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Zaczyna od pocz\u0105tkowego HTML z nadrz\u0119dnego adresu URL. Zasoby, do kt\u00f3rych ten HTML si\u0119 odwo\u0142uje, s\u0105 pobierane p\u00f3\u017aniej, na potrzeby renderowania. <a href=\"https:\/\/developers.google.com\/search\/blog\/2024\/12\/crawling-december-resources\" rel=\"nofollow noopener\" target=\"_blank\">Wpis Google o pobieraniu zasob\u00f3w strony<\/a> m\u00f3wi to wprost: te pocz\u0105tkowe dane mog\u0105 wskazywa\u0107 na JavaScript, CSS, obrazy i filmy, dok\u0142adnie tak jak w przypadku przegl\u0105darki. Kolejno\u015b\u0107 wygl\u0105da tak:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Sprawdzenie robots.txt<\/strong> - zablokowany adres URL jest pomijany, \u017cadne \u017c\u0105danie nie zostaje wys\u0142ane.<\/li>\n<li><strong>\u017b\u0105danie HTTP<\/strong> - robot pobiera HTML strony.<\/li>\n<li><strong>Kolejka renderowania<\/strong> - strona czeka, a\u017c zasoby Google pozwol\u0105 j\u0105 przetworzy\u0107.<\/li>\n<li><strong>Pobieranie zasob\u00f3w<\/strong> - pobierane s\u0105 skrypty, arkusze styl\u00f3w i dane, kt\u00f3re one wywo\u0142uj\u0105.<\/li>\n<li><strong>Wyrenderowany HTML<\/strong> - to on s\u0142u\u017cy do indeksowania i odkrywania link\u00f3w.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Co Web Rendering Service robi z Twoimi zasobami<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Web Rendering Service (w skr\u00f3cie WRS) bierze wszystko, co pobra\u0142, i sk\u0142ada stron\u0119 tak, jak zrobi\u0142aby to przegl\u0105darka u\u017cytkownika. Pod spodem dzia\u0142a headless Chromium, kt\u00f3ry wykonuje JavaScript. Kt\u00f3re strony trafiaj\u0105 do kolejki? <a href=\"https:\/\/developers.google.com\/search\/docs\/crawling-indexing\/javascript\/javascript-seo-basics\" rel=\"nofollow noopener\" target=\"_blank\">Podstawy JavaScript SEO od Google<\/a> podaj\u0105, \u017ce strony z kodem stanu 200 s\u0105 ustawiane w kolejce do renderowania, chyba \u017ce metatag robots albo nag\u0142\u00f3wek ka\u017ce Google ich nie indeksowa\u0107. Oczekiwanie mo\u017ce trwa\u0107 kilka sekund. Ale mo\u017ce te\u017c potrwa\u0107 d\u0142u\u017cej.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Google indeksuje wyrenderowany HTML, a potem analizuje go jeszcze raz w poszukiwaniu link\u00f3w. Dlatego menu, paginacja i bloki z powi\u0105zanymi tre\u015bciami budowane przez skrypty musz\u0105 w tym wyniku przyj\u0105\u0107 posta\u0107 <a href=\"https:\/\/jalvo.eu\/pl\/strony-osierocone-jak-je-znalezc-i-podlinkowac\/\">link\u00f3w wewn\u0119trznych dost\u0119pnych dla robot\u00f3w<\/a>. Je\u015bli tak si\u0119 nie stanie, strony, do kt\u00f3rych prowadz\u0105, pozostaj\u0105 nieodkryte.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Zablokowane pliki JavaScript i inne powody znikania tekstu<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Wyszukiwarka Google nie wyrenderuje JavaScriptu z zablokowanych plik\u00f3w ani na zablokowanych stronach. Wystarczy regu\u0142a disallow w robots.txt na\u0142o\u017cona na skrypt, arkusz styl\u00f3w albo \u015bcie\u017ck\u0119 API, a wyrenderowany HTML powstaje bez tre\u015bci, kt\u00f3re one generuj\u0105. Do tego renderowanie po stronie Googlebota zawodzi tu po cichu: szkielet HTML trafia do indeksu, a tekst nigdy nie dociera. \u017badnego alarmu, nic. Najpierw sprawd\u017a te przyczyny na w\u0142asnym serwerze \u017ar\u00f3d\u0142owym:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>zablokowane \u015bcie\u017cki <em>\/assets<\/em> lub <em>\/api<\/em> w robots.txt,<\/li>\n<li>hosty zasob\u00f3w, kt\u00f3re odrzucaj\u0105 \u017c\u0105dania bot\u00f3w,<\/li>\n<li><a href=\"https:\/\/jalvo.eu\/pl\/rate-limiting-botow-bez-spowalniania-googlebota\/\">limity \u017c\u0105da\u0144, kt\u00f3re blokuj\u0105 roboty<\/a> w trakcie pobierania skrypt\u00f3w,<\/li>\n<li>wywo\u0142ania API zwracaj\u0105ce b\u0142\u0119dy zamiast danych.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Googlebot opiera si\u0119 na kodach stanu HTTP, \u017ceby ustali\u0107, czy co\u015b posz\u0142o nie tak. Aplikacja dzia\u0142aj\u0105ca po stronie klienta, kt\u00f3ra dla brakuj\u0105cej albo pustej strony odpowiada kodem sukcesu, tworzy ba\u0142agan opisany w tek\u015bcie <a href=\"https:\/\/jalvo.eu\/pl\/bledy-soft-404-strony-z-kodem-200\/\">o pozornych b\u0142\u0119dach 404<\/a>. Znaczenie ma te\u017c routing: adresy URL powinny by\u0107 dost\u0119pne przez History API, a nie przez fragmenty. I ka\u017cda poprawka z tej listy dotyczy wszystkich odwiedzaj\u0105cych jednakowo. Chodzi o jedn\u0105 dzia\u0142aj\u0105c\u0105 stron\u0119, a nie o osobn\u0105 wersj\u0119 dla robot\u00f3w.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pobieranie zasob\u00f3w strony a Tw\u00f3j bud\u017cet indeksowania<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ka\u017cdy zas\u00f3b pobrany na potrzeby renderowania uszczupla bud\u017cet indeksowania nazwy hosta, kt\u00f3ra go udost\u0119pnia. \u017beby z\u0142agodzi\u0107 ten koszt, WRS pr\u00f3buje zapisa\u0107 w pami\u0119ci podr\u0119cznej ka\u017cdy plik JavaScript i CSS, do kt\u00f3rego odwo\u0142uj\u0105 si\u0119 renderowane strony, na okres do 30 dni i bez wzgl\u0119du na dyrektywy buforowania HTTP, jak podaje wpis Crawling December o zasobach. Multimedia te\u017c si\u0119 licz\u0105: pobrania wykonywane przez Googlebot-Image i Googlebot-Video zu\u017cywaj\u0105 bud\u017cet witryny.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Co wi\u0119c zrobi\u0107 z bud\u017cetem indeksowania dla plik\u00f3w JS i CSS? To w gruncie rzeczy proste. Im mniej zasob\u00f3w potrzebuje Twoja g\u0142\u00f3wna tre\u015b\u0107, tym mniej bud\u017cetu idzie na renderowanie i tym wi\u0119cej zostaje na inne zadania robota. Google zaktualizowa\u0142 te\u017c wpis 6 grudnia 2024, dodaj\u0105c uwag\u0119 o wp\u0142ywie serwowania zasob\u00f3w z innego originu na wydajno\u015b\u0107. Moim zdaniem warto to rozwa\u017cy\u0107, zanim przeniesiesz zasoby na inn\u0105 nazw\u0119 hosta.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Dlaczego Google mo\u017ce uruchomi\u0107 nieaktualn\u0105 wersj\u0119 Twojego skryptu<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">WRS buforuje agresywnie i mo\u017ce ignorowa\u0107 nag\u0142\u00f3wki buforowania. Skutek uboczny: mo\u017ce wyrenderowa\u0107 stron\u0119 ze starym JavaScriptem albo CSS. Rozwi\u0105zaniem jest <strong>content fingerprinting<\/strong>. Skr\u00f3t zawarto\u015bci pliku staje si\u0119 cz\u0119\u015bci\u0105 jego nazwy, na przyk\u0142ad <em>main.2bb85551.js<\/em>, wi\u0119c ka\u017cda aktualizacja daje nowy adres URL, a po nieaktualn\u0105 kopi\u0119 nikt ju\u017c nie si\u0119ga.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unikaj natomiast parametr\u00f3w zapytania omijaj\u0105cych pami\u0119\u0107 podr\u0119czn\u0105, kt\u00f3re zmieniaj\u0105 si\u0119 przy ka\u017cdym \u017c\u0105daniu, cho\u0107 tre\u015b\u0107 pliku si\u0119 nie zmienia. Nowe adresy URL oznaczaj\u0105 nowe pobrania, a te spalaj\u0105 bud\u017cet na pliki, kt\u00f3re Google ju\u017c ma. Skonfiguruj fingerprinting w swoim narz\u0119dziu do budowania, a potem upewnij si\u0119, \u017ce Tw\u00f3j serwer \u017ar\u00f3d\u0142owy albo NGINX faktycznie poprawnie serwuje pliki z haszem w nazwie.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Jak sprawdzi\u0107, co faktycznie wyrenderowa\u0142 Googlebot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Otw\u00f3rz wyrenderowany HTML w narz\u0119dziu do sprawdzania adres\u00f3w URL albo w te\u015bcie wynik\u00f3w z elementami rozszerzonymi i wyszukaj w nim tekst, kt\u00f3rego brakuje w Google. Liczy si\u0119 tylko tre\u015b\u0107 widoczna w tym wyniku (w przypadku komponent\u00f3w webowych shadow DOM i light DOM s\u0105 w nim sp\u0142aszczane). Dowody przegl\u0105da\u0142bym w tej kolejno\u015bci:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>sam wyrenderowany HTML,<\/li>\n<li>lista zasob\u00f3w, kt\u00f3rych nie uda\u0142o si\u0119 wczyta\u0107,<\/li>\n<li>regu\u0142y robots.txt obejmuj\u0105ce te pliki,<\/li>\n<li>kody stanu skrypt\u00f3w i punkt\u00f3w ko\u0144cowych API.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">W praktyce SEO przy renderowaniu po stronie klienta sprowadza si\u0119 do jednego nawyku: umieszczaj kluczowy tekst i linki w pocz\u0105tkowym HTML tam, gdzie pozwala na to Tw\u00f3j framework, jednakowo dla ka\u017cdego odwiedzaj\u0105cego. Masz przed witryn\u0105 proxy? Obraz si\u0119 nie zmienia - Jalvo przekazuje \u017c\u0105dania do Twojego serwera \u017ar\u00f3d\u0142owego, wi\u0119c regu\u0142y renderowania i zasob\u00f3w pozostaj\u0105 w konfiguracji serwera \u017ar\u00f3d\u0142owego albo CMS-a.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Zasada stoj\u0105ca za JavaScript SEO jest kr\u00f3tka. Google mo\u017ce zindeksowa\u0107 tylko to, co jego renderer jest w stanie pobra\u0107 i zbudowa\u0107. Odblokuj skrypty, arkusze styl\u00f3w i \u015bcie\u017cki API, od kt\u00f3rych zale\u017cy Twoja tre\u015b\u0107, dodaj skr\u00f3t zawarto\u015bci do nazw plik\u00f3w, \u017ceby aktualizacje dostawa\u0142y nowe adresy URL, i sprawdzaj wyrenderowany HTML po ka\u017cdym istotnym wdro\u017ceniu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">FAQ<\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-question-1790879628353-0\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">Czy Googlebot uruchamia JavaScript na ka\u017cdej stronie?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Nie na ka\u017cdej. Strony, kt\u00f3re zwracaj\u0105 kod stanu oznaczaj\u0105cy sukces, trafiaj\u0105 do kolejki renderowania, chyba \u017ce obowi\u0105zuje metatag robots albo nag\u0142\u00f3wek z noindex. Pliki i strony zablokowane w robots.txt nie s\u0105 renderowane wcale, a to, co doda\u0142yby te skrypty, pozostaje poza indeksem.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1790879628353-1\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">Czy pliki JavaScript i CSS zu\u017cywaj\u0105 bud\u017cet indeksowania?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Tak. Ka\u017cde pobranie obci\u0105\u017ca nazw\u0119 hosta, kt\u00f3ra udost\u0119pnia plik, tak\u017ce osobn\u0105, u\u017cywan\u0105 wy\u0142\u0105cznie do zasob\u00f3w. Pami\u0119\u0107 podr\u0119czna WRS ogranicza powt\u00f3rne pobrania, co oszcz\u0119dza bud\u017cet na inne adresy URL. Stabilne nazwy plik\u00f3w ze skr\u00f3tem zawarto\u015bci pomagaj\u0105 tej pami\u0119ci podr\u0119cznej robi\u0107 swoje.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1790879628353-2\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">Dlaczego po wdro\u017ceniu Google pokazuje star\u0105 wersj\u0119 mojej strony?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Poniewa\u017c WRS mo\u017ce ignorowa\u0107 nag\u0142\u00f3wki buforowania i ponownie u\u017cywa\u0107 zasob\u00f3w, kt\u00f3re ju\u017c zapisa\u0142, wi\u0119c renderer mo\u017ce uruchomi\u0107 poprzedni skrypt albo arkusz styl\u00f3w. Rozwi\u0105zuje to content fingerprinting w nazwach plik\u00f3w: zmieniona tre\u015b\u0107 daje inny adres URL, a ten musi zosta\u0107 pobrany na nowo.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Googlebot najpierw pobiera HTML nadrz\u0119dnego adresu URL. Potem Web Rendering Service pobiera pliki JavaScript i CSS, na kt\u00f3re wskazuje ten kod, i buduje stron\u0119 tak, jak zrobi\u0142aby to przegl\u0105darka. A tekst, kt\u00f3ry pojawia si\u0119 dopiero po tym kroku? Trafia do indeksu tylko wtedy, gdy ka\u017cdy wymagany zas\u00f3b jest dost\u0119pny. To JavaScript SEO w pigu\u0142ce i [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":2377,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[182],"tags":[292,224,408,468,472,35],"class_list":["post-2391","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-seo-pl","tag-googlebot-x","tag-indeksowanie","tag-indeksowanie-x","tag-javascript-seo-x","tag-renderowanie","tag-techniczne-seo-pl"],"acf":[],"_links":{"self":[{"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/posts\/2391","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/users\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/comments?post=2391"}],"version-history":[{"count":0,"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/posts\/2391\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/media\/2377"}],"wp:attachment":[{"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/media?parent=2391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/categories?post=2391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jalvo.eu\/pl\/wp-json\/wp\/v2\/tags?post=2391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}