- Published on
Pierwszy projekt w Next.js 13. dynamiczne strony (SSR) generowane na serwerze z plików CSV
- Authors
- Name
- Patryk Nizio
- @patryk_nizio
Next.js - Pierwsza statyczna strona na Next.js a tak naprawdę React ze sterydami.
Dlaczego wybory2023.pl?
Historia rozpoczęła się w 2020 roku, w czasie pandemii COVID-19, gdy w Polsce odbyły się wybory prezydenckie. Wtedy pojawił się pomysł stworzenia prostej, wiralowej gry strategicznej lub klikanej, osadzonej w polskiej rzeczywistości politycznej. Plan zakładał, że gra mogłaby zyskać popularność na platformach takich jak MLH lub Wykop, co pozwoliłoby sprawdzić działanie serwisu i przyniosłoby trochę zabawy.
Kiedy okazało się, że domena wybory2023.pl jest wolna, natychmiast ją zakupiłem. Mineło trochę czasu... Niestety, przypomniałem sobie o byćiu dumnym posiadaczem domeny wybory2023.pl zbyt późno, dopiero we wrześniu 2023 roku. Niecały miesiąc przed wyborami do sejmu i senatu. Brakowało mi inspiracji co do szczegółów i motywacji do dalszego działania, więc postanowiłem zrezygnować z pomysłu gry politycznej. Nie chciałem pozostawić domeny kompletnie nieużywanej, więc w ramach minimalnego wysiłku, mając świadomość, że projekt nie ma szans na sukces, zdecydowałem się umieścić na stronie przynajmniej sondy i wyniki wyborcze.
To był dobry moment żeby sprawdzić jak działa Next.js, który idealnie nadaje się do generowania i cachowania statycznych stron. Jak to się mówi, nie ma nic szybszego niż statyczny HTML na Nginx :) a później tylko load-balancer i wincyj serwerów.
Za źródło danych posłużyła mi oficjalna strona PKW (https://wybory.gov.pl/sejmsenat2023/pl/dane_w_arkuszach) i arkusze z wynikami w postaci plików CSV. Arkusze były wczytywane i przerabiane na stronę www która renderowała się na serwerze. Zrobienie samej strony zajeło mi kilka-kilkanaście godzin. Poniżej linki do projektu:
- Podgląd: (https://2023wybory-pl-git-main-dyzio18.vercel.app/)
- Repozytorium: (https://github.com/Dyzio18/2023wybory.pl/tree/main)
Next.js, co to jest?
Next.js to framework JavaScript, oparty na React. Pozwala generować statyczne strony na serwerze. Statyczne pliki HTML to oczywiście większa wydajność, szybkość ładowania strony i lepsze SEO. To wszystko było już wcześniej ale Next.js czyni to po prostu wygodnym.
W projekcie wykorzystałem wersję 13 - to ma znaczenie bo wersja ta wprowadza kilka istotnych zmian. Najważniejszą zmianą która będzie rzutować również na Twoim nowym projekcie Next.js jest wykorzystanie katalogu app
zamiast pages
. Niby niewielka zmiana a różnica w użyciu jest spora. Zmienia się routing oraz przekazywanie props'ów dla dynamicznych stron.
Katalog app
został wprowadzony w wersji 13, więcej o zmianach przeczytasz na oficjalnej stronie Next.js. Stawiając swoją pierwszą stronę bazowałem na dokumentacji i różnych wpisach/poradnikach. Moje zdziwienie i frustracja były coraz większe gdy kolejne proponowane rozwiązania nie działały. Problem był już ciekawy bo chciałem generować na podstawie pliku CSV, strony dla pojedynczych okręgów wyborczych 2023wybory.pl/sejm/{NrOkręgu}
.
Generowanie statycznych stron i dynamiczny routing
W poprzedniej architekturze opartej na pages
żeby wygenerować statyczne strony dla dynamicznych danych, na przykład: products/{category}/{id}
używaliśmy dwóch metod:
getStaticProps
- pobranie danych dla statycznej strony,getStaticPaths
- generacja dynamicznych ścieżek.
Wiele odpowiedzi na stackoverflow oraz poradników opisują stary sposób. Next.js 13 dalej umożliwia korzystanie z katalogu pages
jednak preferowany jest app
. Ma on więcej funkcjonalności i jest to domyślny katalog który przesłoni routing pages
. App jest zoptymalizowany i pozwala na wygenerowanie większości kodu po stronie serwera. Nie zaleca sie stosowania obu katalogów, tworząc nowy projekt wybierz app
. Miej to na uwadze gdy przeglądasz blogi i dokumentacje. Dopiero wątek na stackoverflow uświadomił mi że są dwie wersje dokumentacji dla Next.js, a ja przez jakiś czas używałem nie tej co trzeba, zonk 😆.
Dla stron opartych na app
powinniśmy użyć generateStaticParams
żeby wygenerować dynamiczny routing. Wczytujemy dane w dowolny sposób i przekazujemy do funkcji generateStaticParams
która zwraca listę z props'ami dla każdej ze stron. Pamiętaj że musimy eksportować generateStaticParams
. Zwracana lista jest iterowana po elementach, na podstawie tego generowane są statyczne strony gdzie do export default function
przekazujemy parametry params
.
W moim przypadku wczytywałem dane z lokalnego pliku CSV, na podstawie arkusza generowałem stronę dla każdego z okręgów wyborczych. Poniżej kod strony:
// file: app/districts/[id].tsx
import { getCsvDistrictIds, getSejmCsvDataByDistrict, getSejmCandidatesCsvDataByDistrict } from '@/lib/getCsvData';
interface PageProps {
params: {
id: number;
data?: any;
};
}
export async function generateStaticParams() {
const paths = getCsvDistrictIds('sejm.csv');
return paths.map((id) => {
return {
params: {
id: id,
},
};
});
}
export default function Page({ params }: PageProps) {
const district = getSejmCsvDataByDistrict(params.id).region;
const candidates = getSejmCandidatesCsvDataByDistrict(params.id).candidates;
return (
<div className='container mx-auto max-w-screen-xl px-4 pb-6 sm:px-6 lg:px-8'>
<h1 className="text-2xl font-bold">Okręg: {params.id}</h1>
{JSON.stringify(district)}
{JSON.stringify(candidates)}
</div>
);
}
Jeśli Cię zainteresowałem możesz zajrzeć do repozytorium i na oficjalną stronę Next.js. Projekt bardzo zyskuje na popularności i wydaję się istotnym rozszerzeniem dla ekosystemu React. Jest to doby wybór szczególnie dla dużych serwisów, blogów, i stron które mocno stawiają na SEO i wydajność. Next.js ma solidny trend wzrostowy i nic nie zapowiada żeby był mniej popularny. Osobiście jestem bardzo zadowolony, uważam że w końcu powstało dobre rozwiązanie dla obsługi React na serwerze. Jest to bardzo kompleksowe rozwiązanie zaakceptowane przez community z dużym wsparciem innych rozwiązań/twórców.