Next.js
V předchozích seminářách jsme představili knihovnu React a technologii Node.js. Nyní se zaměříme na možnosti jejich propojení. Předpokládejme, že chceme spustit aplikaci vytvořenou v knihovně React. Nejprve se dotážeme na webový server, který nám pošle v odpovědi na náš dotaz HTML, CSS a JavaScript. Následně dochází k renderování webové aplikace a spuštění JavaScriptovéhé kódu. V rámci toho je spuštěna knihovna React a je vygenerováno uživatelské rozhraní. Po skončení toto fáze je možné v prohlížeči vidět uživatelské rozhraní. Jelikož je ale renderování uživatelského rozhraní pomocí React knihovny pouze spuštění JavaScriptového kódu, nabízí se možnost jej přesunout na back-end. To se běžně označuje jako server-side rendering.
Samozřejmě ne vše je možné na back-end přesunout, jelikož změnou běhového prostředí ztrácíme přístup k prohlížeči. JavaScriptový kód, který je možné vykonat nezávisle na běhovém prostředí se obvykle označuje jako izomorfní kód. Velká část renderování pomocí knihovny React je izomorfní. Knihovna React používá pro server-side rendering knihovnu Next.js, kterou si představíme.
Server-side rendering
Server-side rendering může nabývat různých podob. Next.js provádí server-side rendering u každé stránky. To znamená, že vygeneruje HTML a CSS pro každou stránku předem a nenechává to na klientovi. Ke každé vyrenderované stránce je připojen minimalistický JavaScriptový kód, který má za úkol zabezpečovat interaktivitu stránky. Když je stránka načtena, je tento kód spuštěn. Tento proces se běžně nazývá hydratace.
Server-side rendering se může provádět při sestavení aplikace. Tomuto server-side renderingu se říká static site generation. Toto se typicky využívá pro statické aplikace, kde nepředpokládáme častou změnu obsahu. Plnohodnotný server-side se provádí při každém požadavku na zobrazení aplikace.
Dodejme, že při server-side renderingu můžeme provádět i různé optimalizace, například automaticky nahradit všechny obrázky moderními formáty, či provádět analýzu výkonnosti.
Zprovoznění aplikace
Pro vytvoření projektu používající knihovnu Next.js je možné použít nástroj create-next-app
. Nejprve si vytvoříme aplikaci.
npx create-next-app aplikace
Výše uvedený příkaz spustí jednoduchého průvodce, který nás provede vytvořením aplikace.
Aplikaci spustíme ve vývojovém módu následujícím příkazem.
npm run dev
Dodejme, že ve vývojovém módu se změny ve zdrojovém kódu automaticky promítají do právě běžící aplikace.
Případně můžeme aplikaci sestavit a spustit příkazy.
npm run dev
npm run start
Struktura projektu
Jednotlivé stránky webové aplikace jsou React komponenty uložené v adresáři pages
. Tyto komponenty jsou renderovány na straně serveru a posílány prohlížeči. Nyní vytvoříme novou stránku test
. Ve složce pages
vytvoříme soubor test.js
s následujícím kódem.
export default function Test() {
return (
<div>
<h1>Test page</h1>
</div>
);
}
Next.js se automaticky postará o routování. Výše vytvořená stránka je dostupná přes URL /test
. Takto vytvořená stránka je statická.
Získání dat
Dynamicky generovanou stránku je možné vytvořit několika způsoby, jelikož máme více možností, kdy budeme stránku renderovat. Pro získání dat při sestavení aplikace (static site generation) slouží funkce getStaticProps()
. Jednoduchý příklad získání dat následuje.
export async function getStaticProps() {
const res = await fetch('https://jsonplaceholder.typicode.com/users/');
const data = await res.json();
return {
props: {
data,
},
};
}
Získaná data jsou dostupná v proměnné data
. Kód níže ukazuje rozšíření naší testovací stránky o výpis těchto dat.
export default function Test({data}) {
return (
<div>
<h1>Test page</h1>
<ul>
{data.map((user, index) => {
return (
<li key={user.id}>{user.name}</li>
);
})}
</ul>
</div>
);
}
Dalším okamžikem, kdy můžeme získat data je server-side renderingu, tedy při požadavku na zobrazení aplikace. V tomto případě se ke získání dat používá funkce getServerSideProps()
. Použití je analogické jako v případě getStaticProps().
export async function getServerSideProps() {
const res = await fetch('https://jsonplaceholder.typicode.com/users/');
const data = await res.json();
return {
props: {
data,
},
};
}
Doposud jsme získávali data na straně serveru. Data můžeme získat i na straně klienta, například následovně.
import { useState, useEffect } from 'react'
export default function getUsers() {
const [data, setData] = useState(null);
async function loadData() {
const res = await fetch('https://jsonplaceholder.typicode.com/users/');
const data = await res.json();
setData(data);
}
useEffect(() => {loadData();}, []);
if (!data) return <p>No data</p>
return (
<Users data={data}/>
);
}
function Users({data}) {
return (
<ul>
{data.map((user) => {
return (
<li key={user.id}>{user.name}</li>
);
})}
</ul>
);
}
Výše uvedený kód využívá React hooks. Jednoduší alternativou je použít SWR což je speciální React hook pro získávání dat poskytovaný Next.js.
import useSWR from 'swr';
const fetcher = url => fetch(url).then(r => r.json())
export default function Test() {
const { data, error } = useSWR('https://jsonplaceholder.typicode.com/users/', fetcher);
if (error) return <div>failed to load</div>;
if (!data) return <div>loading...</div>;
return (
<Users data={data}/>;
)
}
Komponenty
Jednotlivé stránky mohou obsahovat uživatelské či vestavěné komponenty. Knihovna Next.js disponuje několika vestavěnými komponentami, který usnadňují vývoj. Příkladem je komponenta Image
umožňuje vložit obrázek. Tato komponenta provádí různé optimalizace, například provede změnu velikosti obrázku, převede jej do formátu WebP a také předchází CLS (Cumulative layout shift).
import Image from 'next/image';
const YourComponent = () => (
<Image
src="/images/profile.jpg" // cesta k obrázku
height={42} // výška
width={42} // šířka
alt="popisek"
/>
);
Další užitečné komponenty jsou Head
, která slouží pro vložení hlavičky webové stránky nebo komponenta Script
umožňující vložení externího JavaScriptového kódu.
Vizualizace komponent
Vizualizace komponent je v knihovně Next.js založena na CSS modulech. To, zjednodušeně řečeno, znamená, že vizualizace jednotlivých komponent je nezávislá na ostatních.
Abychom vizualizovali komponentu, je nutné nejprve vytvořit CSS modul. V knihovně Next.js to uděláme jednoduše tak, že vytvoříme soubor s příponou .module.css
. Například pro naši testovací stránku vytvoříme soubor test.module.css
ve složce styles
s následujícím obsahem.
.textColorPrimary {
color: blue;
}
Připomeňme, že CSS moduly pracujíc s CSS jako s JavaScriptovými objekty, není tedy možné používat pomlčky v selektorech. Navíc není možné používat selektory neobsahující třídu. Následující kód ukazuje načtení CSS modulu a jeho použití.
import styles from '../styles/test.module.css';
export default function Test() {
return (
<div>
<h1 className={styles.textColorPrimary}>Test page</h1>
</div>
);
}
CSS pravidla uvedená v souboru global.css
jsou dostupná ve všech komponentách. Ve skutečnosti se jedná o běžný CSS soubor a je zde možné používat selektory bez omezení.
Kam dál
Projekt vytvořený pomocí Next.js je možné poměrně jednoduše nasadit na platformu Vercel. Dodejme, že k této knihovně existuje několik alternativ. Například knihovna Gatsby, která se spíše zaměřuje na static site rendering nebo knihovna Remix.Zadání
-
úkol 1 (dobrovolný)
Zprovozněte projekt pomocí
create-next-app
a vyzkoušejte příklady uvedené v tomto semináři.