Przejdź do treści

Portfolio w Astro: jak zdobyć 100/100 w PageSpeed Insights?

Case study migracji portfolio UI/UX designera z WordPressa do Astro: statyczna architektura, responsywne obrazy, minimum JavaScriptu, SEO i wynik 100/100 w PageSpeed Insights.

Maciej Sala

Founder StriveLab

10 min czytaniaOpublikowano

Migracja portfolio z WordPressa do Astro: rezultat

Przepisując portfolio UI/UX designera z WordPressa do Astro, nie chciałem jedynie odwzorować istniejącego wyglądu. Zależało mi przede wszystkim na uproszczeniu całej architektury i zbudowaniu witryny, która będzie szybka od samego początku i bez jakichkolwiek dodatkowych optymalizacji.

wynik PageSpeed Insights
100/100wynik PageSpeed Insights
indeksowalne dokumenty HTML
22indeksowalne dokumenty HTML
case studies w wersjach EN i PL
7 × 2case studies w wersjach EN i PL
Wynik 100 punktów w kategoriach wydajność, ułatwienia dostępu, sprawdzone metody i SEO dla mobilnej wersji portfolio UX designera

Portfolio UX designera na WordPressie: punkt wyjścia

Pierwsza wersja strony korzystała z WordPressa i motywu Perfect Portfolio, podczas gdy nowa witryna miała zachować charakter pierwowzoru, ale jednocześnie lepiej odpowiadać aktualnym potrzebom:

  • Prezentować siedem projektów z obszarów UX, gier, AdTech i oprogramowania enterprise.

  • Działać w języku angielskim i polskim.
  • Sprawnie wyświetlać dużą liczbę makiet i zrzutów ekranów.

  • Zapewniać proste dodawanie oraz porządkowanie treści.
  • Poprawnie obsługiwać SEO każdej wersji językowej.
  • Nie wymagać bazy danych, panelu administracyjnego ani backendu.

  • Dać się wdrożyć na dowolnym hostingu plików statycznych.

Widok dwujęzycznego portfolio UX designera z filtrowaną siatką case studies

To ostatnie założenie miało duże znaczenie, ponieważ samo w sobie portfolio jest serwisem mocno opartym o treść. Użytkownik przegląda strony, potem filtruje projekty i otwiera galerie, więc nie posiada logowania, koszyka, spersonalizowanego panelu ani danych aktualizowanych w czasie rzeczywistym. Budowanie do tego pełnej aplikacji klienckiej oznaczałoby wysłanie do przeglądarki większej ilości kodu niż rzeczywiście potrzebuje użytkownik.

W związku z powyższym wybór padł na Astro.

Dlaczego Astro sprawdziło się w portfolio UI/UX designera

było rozwiązaniem z kilku powodów. Przede wszystkim dlatego, że pozwala budować interfejsy z komponentów, ale domyślnie renderuje je do czystego HTML-a. Z kolei kod poszczególnych komponentów wykonuje się w trakcie budowania strony, a nie podczas każdej wizyty użytkownika. W związku z powyższym do przeglądarki trafia lekki dokument, same style oraz wyłącznie ten JavaScript, który odpowiada za obsługę faktycznych interakcji.

W przypadku tego portfolio przyniosło to kilka korzyści naraz:

  • cała podstawowa treść jest dostępna od razu w HTML;
  • nie trzeba pobierać runtime'u Reacta, Vue ani innego frameworka klienckiego;
  • każda realizacja ma osobny, statyczny adres;
  • komponenty nadal pozwalają współdzielić layout, nawigację i typy bloków treści;
  • obrazy mogą zostać przetworzone już podczas buildu;
  • wynikowy katalog dist/ można opublikować na prostym hostingu statycznym.

Zależności produkcyjne projektu dobrze pokazują jego skalę. Poza samym Astro użyłem tylko integracji generującej sitemapę:

Code
{
  "dependencies": {
    "@astrojs/sitemap": "^3.7.3",
    "astro": "^7.1.5"
  }
}

Mała liczba zależności nie gwarantuje automatycznie szybkiej strony, ale ułatwia kontrolowanie jej złożoności.

Architektura Astro: jedno źródło danych i 22 statyczne strony

Architektura projektu składa się z trzech warstw: typowanych danych, komponentów Astro i statycznego wyniku buildu. Poniżej przedstawiam pełny przepływ:

Diagram
Od typowanych danych do statycznych stron portfolio dostarczanych przez CDN.

Treści wspólne, SEO i realizacje znajdują się odpowiednio w plikach site.ts, seo.ts oraz portfolio.ts. Komponenty odpowiadają za prezentację, a pliki w src/pages składają wszystko w kompletne trasy.

Każde case study ma tytuł, kategorię, obraz wiodący i uporządkowaną listę bloków. Blok może być akapitem, nagłówkiem, listą, galerią, metryką, linkiem do sklepu albo plikiem do pobrania. Dzięki temu projekty o bardzo różnych historiach korzystają ze wspólnego renderera, ale nie muszą mieć identycznej struktury.

Dynamiczna trasa Astro generuje wszystkie realizacje podczas buildu:

Code
export function getStaticPaths() {
  return Object.values(caseStudies).map((study) => ({
    params: { slug: study.slug },
    props: { study },
  }));
}

Ten sam mechanizm obsługuje również polską wersję językową. Angielskie podstrony portfolio znajdują się bezpośrednio pod adresem /portfolio/{slug}/, a polskie pod /pl/portfolio/{slug}/. Uwzględniając strony główne, kontakt, sekcję o autorze oraz listy projektów, proces budowania generuje łącznie 22 indeksowalne dokumenty HTML oraz osobną stronę 404.

Dzięki temu użytkownik nie musi czekać, aż JavaScript pobierze dane i złoży widok w przeglądarce – gotowa, w pełni sformatowana treść dociera do niego bezpośrednio w odpowiedzi z serwera.

Optymalizacja JavaScriptu w Astro: minimum kodu po stronie klienta

W repozytorium nie ma komponentów hydratowanych przez dyrektywy client:*. Własny JavaScript po stronie przeglądarki odpowiada tylko za trzy (oprócz niewielkiego mechanizmu prefetch dostarczanego przez Astro):

  • otwieranie menu mobilnego;
  • filtrowanie siatki portfolio;
  • obsługę lightboxa w galeriach case studies.

Filtr projektów nie wysyła żadnego zapytania sieciowego. Zmienia jedynie stan przycisków i atrybut hidden gotowych kart HTML:

Code
cards.forEach((card) => {
  const show = filter === 'all' || card.dataset.category === filter
  card.toggleAttribute('hidden', !show)
})

Nawet jeśli JavaScript w ogóle się nie uruchomi, użytkownik bez problemu zobaczy wszystkie projekty i otworzy każdą realizację. Skrypty stanowią tu jedynie dodatkowe ułatwienie, a nie warunek konieczny do uzyskania dostępu do treści.

Takie podejście skutecznie skraca czas parsowania i wykonywania kodu, a także pomaga utrzymać niski wskaźnik . Główny wątek przeglądarki nie musi bowiem tracić zasobów na inicjalizację rozbudowanej aplikacji tuż po wyrenderowaniu strony.

Optymalizacja obrazów w portfolio Astro

Portfolio UX ma charakter wizualny, przez co w tym projekcie głównym obciążeniem transferu nie jest wcale kod, lecz portret, logotypy, makiety produktów oraz galerie ekranów. To właśnie zasoby graficzne wymagały najbardziej świadomego i przemyślanego podejścia.

Oryginalne pliki graficzne znajdują się w katalogu src/assets/images, a komponent Image dostarczany przez przetwarza je automatycznie podczas budowania strony. Same dane portfolio operują na czytelnych ścieżkach tekstowych, podczas gdy nieskomplikowany resolver mapuje je w locie na metadane wymagane przez silnik Astro.

Dzięki temu jeden obraz źródłowy może otrzymać kilka wariantów dopasowanych do miejsca, w którym jest wyświetlany. Karta projektu korzysta z mniejszych szerokości:

Code
<Image
  src={resolveImage(heroImage(item.slug))!}
  alt={item.title}
  widths={[300, 600]}
  sizes="(max-width: 700px) 100vw, 350px"
  loading={i < eagerImageCount ? 'eager' : 'lazy'}
/>

Z kolei szeroki obraz otwierający case study może potrzebować większych wariantów:

Code
<Image
  src={heroImage}
  alt={`${study.title} — hero`}
  widths={[600, 1000, 1400]}
  sizes="(max-width: 900px) 100vw, 820px"
  loading="eager"
  fetchpriority="high"
/>

Istotne są tutaj trzy decyzje. Po pierwsze, parametr widths definiuje zestaw szerokości, jakie mają zostać wygenerowane, a atrybut sizes informuje przeglądarkę, jaką przestrzeń w layoutach poszczególnych urządzeń faktycznie zajmie dany obraz. Dzięki temu rozwiązaniu mechanizm renderujący może inteligentnie dobrać odpowiedni plik zamiast pobierać największy wariant grafiki niezależnie od ekranu.

Po drugie, obrazy znajdujące się poza pierwszym ekranem są ładowane leniwie i dlatego przeglądarka nie musi pobierać całej galerii, zanim pokaże początek strony. Wyjątkiem są elementy widoczne od razu, czyli portret na stronie głównej, grafika hero realizacji i pierwsze karty portfolio.

Po trzecie, prawdopodobny element otrzymuje fetchpriority="high", co jasno komunikuje przeglądarce, że ten zasób powinien zostać pobrany wcześniej.

Dodam jeszcze, że większość dużych grafik została również zapisana w WebP, a jawne wymiary i stałe proporcje placeholderów rezerwują miejsce przed pobraniem pliku, co ogranicza przesunięcia layoutu i pomaga utrzymać niski .

Najważniejsza lekcja z tej części projektu jest to, że samo użycie komponentu optymalizującego obrazy nie wystarczy, ponieważ w dalszym ciągu trzeba prawidłowo określić ich rozmiar w layoucie, kolejność ładowania i znaczenie dla pierwszego widoku.

Lekki CSS zamiast rozbudowanej biblioteki UI

Interfejs został zbudowany bez biblioteki komponentów i bez dużego frameworka CSS. Globalny arkusz zawiera tokeny kolorów, typografii, odstępów i szerokości kontenera. Style specyficzne dla widoku pozostają przy komponentach Astro.

Responsywność opiera się głównie na CSS Grid, clamp() i kilku czytelnych media queries. Przykładowo siatka usług sama dopasowuje liczbę kolumn do dostępnej przestrzeni:

Code
.services {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--gap);
}

Projekt nie pobiera fontów z zewnętrznego serwera. Stos typograficzny zawiera nazwy Inter i Poppins, ale bez blokującego importu przechodzi do fontów systemowych dostępnych na urządzeniu. Oznacza to mniej żądań i brak oczekiwania na zewnętrzny zasób przed narysowaniem tekstu. Poza tym CSS uwzględnia też preferencję prefers-reduced-motion.

Prefetch w Astro i szybkość kolejnych przejść

Pierwsze wyświetlenie strony to tylko część doświadczenia portfolio, ponieważ równie ważne jest przechodzenie między kartą projektu a jego opisem. W konfiguracji Astro włączyłem prefetch linkowanych dokumentów:

Code
export default defineConfig({
  site: 'https://michalbialik.com',
  prefetch: { prefetchAll: true },
})

Ponieważ strony są statyczne i stosunkowo małe, przeglądarka może wcześniej pobrać dokumenty, do których prawdopodobnie przejdzie użytkownik i dzięki temu nawigacja po portfolio sprawia wrażenie niemal natychmiastowej.

Mechanizm prefetch nie tłumaczy jednak wyniku pierwszego wejścia w PageSpeed. To osobna optymalizacja, która odpowiada za odczuwalną szybkość nawigacji po kolejnych podstronach i warto dokładnie tak do niej podchodzić.

SEO i dostępność portfolio w Astro

Projektowanie szybkiej witryny nie powinno oznaczać ignorowania dostępności i SEO w Astro, więc dlatego wspólny layout stron odpowiada również za:

  • poprawny atrybut języka dokumentu;
  • link kanoniczny dla każdej trasy;
  • alternatywne adresy hreflang dla wersji EN, PL i x-default;
  • metadane Open Graph oraz Twitter Cards;
  • dane strukturalne Person, ProfilePage, BreadcrumbList i CreativeWork;
  • pomijanie strony 404 w indeksowaniu.

Interfejs uwzględnia semantyczne nagłówki, link pomijający zawartość, wyraźny wskaźnik fokusu, etykiety ARIA oraz oznaczenie aktywnej strony. Kolor drobnych tekstów akcentowych został przyciemniony z #e8505b do #c83c47, dzięki czemu kontrast na białym tle wzrósł z 3,67:1 do 5,01:1, spełniając wymóg normy WCAG AA.

Choć te elementy nie wpływają bezpośrednio na wynik w testach Performance, stanowią integralną część tej samej definicji jakości. Strona ma być szybka, łatwa do odnalezienia i wygodna dla jak najszerszego grona użytkowników.

Projekt wyposażono również w autorski skrypt regresji SEO, który po każdym zbudowaniu aplikacji weryfikuje kompletność linków kanonicznych, hreflang, sitemapy, pliku robots.txt, metadanych social oraz danych strukturalnych JSON-LD:

Code
npm run build
npm run seo:check

Taka prosta automatyzacja chroni przed przypadkowym usunięciem technicznych fundamentów podczas dalszego rozwoju.

Jak mierzyć wynik 100/100 w PageSpeed Insights

Trzeba pamiętać, że sam wynik PageSpeed Insights może zmienić się wraz z treścią, sposobem hostowania, wersją Lighthouse, obciążeniem sieci albo dodaniem zewnętrznego skryptu. W związku z powyższym taka liczba bez kontekstu ma ograniczoną wartość.

Pomiar tego projektu warto dokumentować według stałej procedury:

  1. Testować wersję produkcyjną, a nie serwer developerski.
  2. Wykonać osobne testy mobile i desktop.
  3. Powtórzyć pomiar przynajmniej trzy razy i podać medianę.
  4. Zapisać datę, adres strony i wersję testowanego widoku.
  5. Poza wynikiem ogólnym pokazać FCP, LCP, TBT, CLS i Speed Index.
  6. Przetestować zarówno stronę główną, jak i cięższe case study z galerią.
  7. Oddzielić dane laboratoryjne Lighthouse od terenowych danych CrUX.

Warto wprost zaznaczyć, że wynik 100/100 pochodzi z testów laboratoryjnych, a nie odzwierciedla realnych doświadczeń wszystkich użytkowników. Brak danych terenowych to normalny stan dla nowej lub mało odwiedzanej strony, która może po prostu nie posiadać wystarczającej liczby próbek ruchu.

Kompromisy i dalszy rozwój portfolio w Astro

Astro z pewnością było odpowiednim wyborem, jeśli chodzi o framework, ale trzeba pamiętać o kilku rzeczach na przyszłość. Pierwsza sprawa to treści case studies, które znajdują się obecnie w dużym pliku TypeScript. O ile sam blokowy model jest bezpieczny typowo i dobrze współpracuje ze wspólnym rendererem, to przy dalszym rozwoju może stać się niewygodny redakcyjnie. Poza tym, w repozytorium projektu ma już przygotowaną kolekcję treści dla przyszłego bloga i jeśli zajdzie taka potrzeba, może zostać w każdej chwili dodany. Wtedy naturalnym kolejnym krokiem będzie przeniesienie treści do Astro Content Collections lub MDX.

Obsługa dwujęzycznego routingu również wymaga dużej dyscypliny, ponieważ polskie i angielskie strony informacyjne posługują się odmiennymi slugami, przez co część mapowania znaczników hreflang trzeba konfigurować ręcznie. Z drugiej jednak strony mamy pełną kontrolę nad adresami URL.

Z kolei wyniki wydajności należy traktować jak ściśle kontrolowany budżet i dlatego każde przyszłe wdrożenie analityki bezpośrednio zwiększa transfer danych oraz obciąża główny wątek przeglądarki. Chodzić może tutaj o użycie zewnętrznych fontów, widgetu newslettera, osadzonego wideo czy kolejnych integracji. Dodanie każdego kolejnego elementu musi mieć swoje uzasadnienie.

Efekt migracji portfolio z WordPressa do Astro

Projekt zakończył się powstaniem statycznego, dwujęzycznego portfolio o następujących cechach:

ObszarRezultat
ArchitekturaAstro 7, statyczny HTML, bez frameworka klienckiego
Zakres22 indeksowalne strony, siedem case studies w EN i PL oraz strona 404
Obrazyresponsywne warianty generowane przez astro:assets
JavaScriptmenu mobilne, filtrowanie portfolio i lightbox
SEOlinki kanoniczne, hreflang, sitemap, social meta i dane strukturalne
Dostępnośćsemantyczny HTML, obsługa klawiatury, focus i kontrast WCAG AA
Wydajność100/100 w laboratoryjnym pomiarze PageSpeed Insights

Największą zmianą nie była jednak konkretna metryka, lecz całkowite odwrócenie sposobu myślenia o optymalizacji. Zamiast budować ciężką aplikację, a potem próbować ją odchudzić, zacząłem od statycznego dokumentu i dokładałem wyłącznie te elementy, których użytkownik realnie potrzebował.

Ultraszybkie projekty, łączące lekkość ze skalowalnością.
Astro

Często zadawane pytania

Dlaczego Astro dobrze sprawdza się w portfolio?

Portfolio jest zwykle serwisem treściowym, który nie potrzebuje rozbudowanej aplikacji działającej w przeglądarce. Astro może wygenerować gotowy HTML podczas buildu i wysłać JavaScript tylko dla rzeczywistych interakcji, takich jak menu, filtrowanie projektów czy lightbox.

Co miało największy wpływ na wynik 100/100 w PageSpeed Insights?

Największe znaczenie miał zestaw decyzji architektonicznych: statyczne generowanie stron, brak hydratowanego frameworka klienckiego, responsywne obrazy przetwarzane podczas buildu, jawne wymiary grafik i ograniczenie skryptów do progresywnych ulepszeń.

Czy samo użycie astro:assets gwarantuje szybkie obrazy?

Nie. Komponent Image pomaga generować warianty i nowoczesne formaty, ale nadal trzeba poprawnie ustawić widths, sizes, loading i priorytet obrazu LCP. Ważne są również rozmiar źródła oraz miejsce grafiki w layoucie.

Czy wynik 100/100 w PageSpeed jest stały?

Nie. Wynik laboratoryjny może zmieniać się wraz z wersją Lighthouse, hostingiem, obciążeniem sieci, treścią i skryptami zewnętrznymi. Dlatego pomiar należy archiwizować z datą, adresem, profilem urządzenia i szczegółowymi metrykami.

Czy statyczne portfolio może mieć interaktywne elementy?

Tak. Statyczny HTML może zostać uzupełniony niewielkimi skryptami do menu, filtrowania i galerii. Kluczowe jest to, aby podstawowa treść i nawigacja pozostały dostępne także wtedy, gdy JavaScript się nie uruchomi.

O autorze

Maciej Sala

Maciej Sala — konsultant technologiczny produktów cyfrowych i web developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwija własne projekty.

Pomagam przekładać takie tematy na konkretne wdrożenia w frontendzie, SEO, analityce i procesie produktowym.

Skontaktuj się ze mną
LH.pl – Hosting Mango

Biblioteka wiedzy na temat Astro

Czytaj dalej

Zobacz więcej wpisów
Jak zdobyć 100/100 w Lighthouse z Astro? Case Study

Astro startuje z przewagą, na którą w Next.js trzeba zapracować: domyślnie wysyła zero JavaScriptu, więc świeży projekt często ma Lighthouse powyżej 95 bez jednej optymalizacji. Droga od wyniku „prawie 100” do perfekcyjnego „100/100” w PageSpeed to kwestia detali i dlatego pokazuję, jak zoptymalizować obrazy, fonty oraz skrypty zewnętrzne, i czy gra jest warta świeczki.

Maciej Sala

Maciej Sala

Founder StriveLab

Przewodnik po projektach w Astro od architektury po utrzymanie

Strona internetowa może mieć świetny wynik PageSpeed, a mimo to wciąż mieć różne problemy, poczynając od blokowania publikacji artykułów, a kończąc na gubieniu zapytania z formularza. Stworzyłem ten przewodnik, by sprawnie prowadził przez wybór technologii, migrację, model treści, rendering, SEO i testy, aż po wdrożenie i utrzymanie. Szczegółowe rozwiązania znajdziesz w materiałach przypisanych do poszczególnych etapów.

Maciej Sala

Maciej Sala

Founder StriveLab

Astro vs Next.js w 2026: porównanie frameworków

Astro czy Next.js? Wybór frameworka musi być dokładnie przemyślany, zanim pojawi się pierwszy commit. Jeśli stoisz przed takim właśnie wyborem, w tym artykule staram się wykazać, w jakich obszarach najlepiej sprawdza się Astro , a w jakich będzie dominował Next.js .

Maciej Sala

Maciej Sala

Founder StriveLab

LH.pl – Cloud Server 1C4G