Audyt skryptów JS w 30 sekund
Każdy specjalista SEO wie, że szybkość strony wpływa na ranking i konwersję. Częstym winowajcą problemów z wydajnością jest JavaScript. Skrypty (analityczne, reklamowe, funkcjonalne) mogą blokować renderowanie strony i opóźniać interaktywność. W kilkanaście sekund, bez żadnych skomplikowanych narzędzi możesz przeprowadzić wstępny audyt ładowania skryptów na dowolnej stronie.

Jak sprawdzić skrypty w konsoli (async/defer) – ultra szybki audyt
3 proste kroki żeby skorzystać ze skryptów:
- Wejdź na adres, który chcesz audytować, np. seekio.pl/render-budget/ albo na inną z większą zawartością skryptu (np. nike, google sheets)
- Naciśnij F12 (DevTools) -> zakładka Konsola (Console)
- Wklej kod i enter.
Poniższy kod wyświetli dokładną listę skryptów wskazując wszystkie <script> na danej stronie. Wyświetli: adres (src), atrybuty async i defer.
Array.from(document.scripts).map(s => ({ src: s.src, async: s.async, defer: s.defer }));Jednak wersja ta jest mało czytelna, dlatego polecam ulepszoną wersję ze zdecydowanie lepszym UX oraz dodatkową informacją, type=”module”. Skrypty module nie blokują parsera, ponieważ są domyślnie jako defer.
console.table(
Array.from(document.scripts).map(s => ({
src: s.src || '[inline]',
async: s.async,
defer: s.defer,
module: s.type === 'module'
}))
);Wyświetlanie tylko skryptów potencjalnie blokujących renderowanie
console.table(
Array.from(document.scripts)
.filter(s => s.src && s.type !== 'module' && !s.async && !s.defer)
.map(s => ({ src: s.src, async: s.async, defer: s.defer }))
);Userscript – najwygodniejsze rozwiązanie
Jestem wielkim fanem rozszerzenia TamperMonkey i mam całkiem sporo różnego rodzaju skryptów zapisanych. O to jeden z nich, który pozwala mi na szybki i przede wszystkim wygodny audyt. Na dole strony pojawia się napis „JS” na czarnym tle, który pokazuje wszystkie dobre i potencjalnie blokujące skrypty wraz ze wszystkimi wymaganymi informacjami.
Skrypt można pobrać bezpośrednio z mojego github. Jeśli już masz rozszerzenie typu TamperMonkey, to wystarczy zainstalować skrypt.
Jak interpretować wyniki
Po wklejeniu kodu w konsoli zobaczysz tabelę z informacjami. Generalnie skrypt blokuje renderowanie strony, jeśli jednocześnie jest z zewnętrznego źródła i ma async: false, defer: false i module: false.
Co oznaczają kolumny
- src: adres pliku JS. [inline] to skrypt w HTML bez src
- async: atrybut async (dla classic i module; przy inline nie działa)
- defer: atrybut defer (działa tylko dla classic zewnętrznych)
- module: true, gdy type=”module” (dla inline i zewnętrznych)
Najważniejsze zasady
- module = true
- Domyślnie zachowuje się jak defer: nie blokuje parsera, wykonuje się po parsowaniu HTML
- Kolejność między modułami jest zachowana (chyba że dodasz async)
- async = true przy module -> „async module” – niegwarantowana kolejność względem innych modułów
- defer przy module jest ignorowane (nie zmienia zachowania)
- module = false (classic)
- Zewnętrzny bez async/defer -> potencjalnie blokujący (zatrzymuje parser w miejscu)
- Zewnętrzny z defer -> nie blokuje – wykona się po parsowaniu, kolejność zachowana
- Zewnętrzny z async -> nie blokuje – wykona się jak tylko pobierze, kolejność niegwarantowana
- [inline] (classic) -> wykonuje się natychmiast w miejscu, może blokować parser. Atrybuty async/defer przy inline nie działają (nawet jeśli atrybut widnieje w HTML)
Skrypt blokujący renderowanie
| src | async | defer | module |
|---|---|---|---|
| https://…/skrypt.js | false | false | false |
Taki wynik jest najgorszy przypadkiem i głównym cel do optymalizacji. Skrypt jest zewnętrzny i nie ma żadnego z atrybutów, które pozwoliłyby przeglądarce ładować go w tle. Przeglądarka zatrzymuje parsowanie HTML -> pobiera ten plik -> wykonuje go i dopiero wtedy wraca do budowania reszty strony.
Wpływ na SEO? Bezpośrednio opóźnia ładowanie widocznych treści, pogarszając Core Web Vitals (FCP, LCP)
Skrypt asynchroniczny (async)
| src | async | defer | module |
|---|---|---|---|
| https://…/skrypt.js | true | false | false |
Taki wynik jest prawidłowy, ponieważ atrybut async: true mówi przeglądarce: „Pobierz ten skrypt w tle i uruchom go jak tylko się pobierze”. Jeśli masz kilka skryptów z atrybutem async, zostaną one wykonane w kolejności zakończenia ich pobierania, a nie w kolejności występowania w kodzie. Czyli mniejszy skrypt pobierze się szybciej.
Wpływ na SEO? Pozytywny – skrypt nie blokuje renderowania. Idealny dla zewnętrznych skryptów (analityka, reklamy, widgety, etc), które są niezależne od reszty strony.
Skrypt odroczony (defer)
| src | async | defer | module |
|---|---|---|---|
| https://…/skrypt.js | false | true | false |
To złoty środek dla skryptów modyfikujących stronę. Atrybut defer: true mówi przeglądarce: „Pobierz ten skrypt w tle i poczekaj z jego wykonaniem aż cały HTML zostanie załadowany. Jeśli jest więcej skryptów z defer, wykonaj je w takiej kolejności, w jakiej występują w kodzie”.
Gwarantuje kolejność wykonania, tzn że skrypty wykonają się w takiej samej kolejności, w jakiej znajdują się w kodzie HTML. Skrypt „ma pewność”, że wszystkie elementy HTML (przyciski, formularze, divy) już istnieją, gdy zaczyna działać.
Wpływ na SEO? Idealny, bo nie blokuje renderowania, a jednocześnie ma gwarancję, że uruchomi się, gdy wszystkie elementy strony (DOM) będą już dostępne.
Wydajne rozwiązanie
| src | async | defer | module |
|---|---|---|---|
| https://…/skrypt.js | false | false | true |
Gdy zobaczysz taki wynik – jest bezpiecznie – można zostawić, bo oznacza, że skrypt został załadowany z type="module". Moduły JavaScript są domyślnie odroczone (defer). Oznacza to, że zachowują się tak, jakby miały atrybut defer, nawet jeśli go nie mają.
Wpływ na SEO? Taki sam jak w przypadku defer: true. Skrypt jest bezpieczny i nie blokuje renderowania.
Skrypt wewnętrzny (inline)
| src | async | defer | module |
|---|---|---|---|
| [inline] | false | false | false |
Skrypt jest osadzony bezpośrednio w kodzie HTML i jego wpływ zależy od lokalizacji:
- W
<head>– jeśli jest duży, to może blokować renderowanie. Musi zostać wykonany, zanim przeglądarka przejdzie do<body> - Na końcu
<body>– strona jest w większości wyrenderowana, więc przeważnie nie ma problemu
Wpływ na SEO? Polecam unikać dużych skryptów inline w sekcji <head>. Jeśli to możliwe, przenieś je do zewnętrznego pliku z atrybutem defer.
Kiedy korzystać z async, a kiedy defer?
To zależy 🙂
Wybór zależy od tego co dany skrypt robi i czy jest zależny od innych skryptów lub elementów na stronie.
Atrybuty async/defer mają jeden wspólny cel – pobranie skryptu w tle, nie blokując przy tym budowania strony. Różnica? Kiedy skrypt zostanie wykonany.
async – dla zewnętrznych skryptów
Używaj go dla skryptów, które są w 100% zewnętrzne i samowystarczalne. Przykłady:
- Skrypty analityczne – Google Analytics, Hotjar, Clarity
- Skrypty reklamowe – Google AdSense, Ezoic
- Wszelkiego rodzaju widgety – np. social media
- Skrypty firm trzecich (third-party) – czaty, systemy do notyfikacji push, helpdesk
defer – dla zależnych od strony
Używaj go dla skryptów, które muszą wchodzić w interakcję z elementami na stronie, przykłady:
- Główna logika aplikacji – skrypty, które dodają interaktywność, np. obsługa menu, formularzy, przycisków „kup teraz”, „załaduj więcej”
- Manipulacja DOM – każdy skrypt, który używa
document.getElementById()lubdocument.querySelector(). - Biblioteki i frameworki – jeśli ładujesz bibliotekę (np. jQuery, którą można znaleźć na wielu stron opartych o WordPress) i skrypt, który jej używa – oba powinny mieć
defer, aby zachować kolejność. - Interaktywne elementy – skrypty do sliderów, karuzel, dynamicznych galerii.
Porównanie async vs defer
| Cecha | Zwykły <script> | <script async> | <script defer> |
|---|---|---|---|
| Blokuje parsowanie HTML? | 🔴 TAK | 🟢 NIE | 🟢 NIE |
| Kiedy się wykonuje? | Od razu i wszystko blokuje | Gdy się pobierze | Po załadowaniu całego HTML |
| Gwarancja kolejności? | 🟢 TAK | 🔴 NIE | 🟢 TAK |
| Najlepszy dla… | Małych, krytycznych skryptów w <head> | Niezależnych skryptów firm trzecich | Głównej logiki strony, interakcji |
