Страницы (Pages)¶
Страница — это компонент React, который экспортируется из файла с расширением .js
, .jsx
, .ts
или .tsx
, находящегося в директории pages
. Каждая страница ассоциируется с маршрутом (роутом) по названию. Например, страница pages/about.js
будет доступна по адресу /about
. Обратите внимание, что страница должна экспортироваться по умолчанию (export default
):
export default function About() {
return <div>О нас</div>;
}
Маршрут для страницы pages/posts/[id].js
будет динамическим, т. е. такая страница будет доступна по адресам posts/1
, posts/2
и т. д.
По умолчанию все страницы рендерятся предварительно (pre-rendering). Это приводит к лучшей производительности и SEO. Каждая страница ассоциируется с минимальным количеством JS. При загрузке страницы запускается JS-код, который делает ее интерактивной (данный процесс называется гидратацией — hydration).
Существует 2 формы предварительного рендеринга: генерация статической разметки (static generation, SSG, рекомендуемый подход) и рендеринг на стороне сервера (server-side rendering, SSR). Первая форма предусматривает генерацию HTML во время сборки и его повторное использование при каждом запросе. Вторая — генерацию разметки при каждом запросе. Генерация статической разметки является рекомендуемым подходом по причинам производительности.
Кроме этого можно использовать рендеринг на стороне клиента (client-side rendering), когда определенные части страницы рендерятся клиентским JS.
SSG¶
Генерироваться могут как страницы с данными, так и страницы без данных.
Без данных
export default function About() {
return <div>О нас</div>;
}
Существует 2 возможных сценария, при которых может потребоваться генерация статической страницы с данными:
- Контент страницы зависит от внешних данных: используется
getStaticProps
- Пути (
paths
) страницы зависят от внешних данных: используетсяgetStaticPaths
(как правило, совместно сgetStaticProps
)
Контент страницы зависит от внешних данных¶
Предположим, что страница блога получает список постов от CMS:
// TODO: запрос `posts`
export default function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
Для получения данных, необходимых для предварительного рендеринга, из файла должна экспортироваться асинхронная функция getStaticProps
. Данная функция вызывается во время сборки и позволяет передавать полученные данные странице в виде props
:
export default function Blog({ posts }) {
// ...
}
export async function getStaticProps() {
const posts = await (
await fetch('https://example.com/posts')
)?.json();
// обратите внимание на сигнатуру
return {
props: {
posts,
},
};
}
Пути страницы зависят от внешних данных¶
Для обработки предварительного рендеринга статической страницы, пути которой зависят от внешних данных, из динамической страницы (например, pages/posts/[id].js
) должна экспортироваться асинхронная функция getStaticPaths
. Данная функция вызывается во время сборки и позволяет определить пути для пререндеринга:
export default function Post({ post }) {
// ...
}
export async function getStaticPaths() {
const posts = await (
await fetch('https://example.com/posts')
)?.json();
// обратите внимание на структуру возвращаемого массива
const paths = posts.map((post) => ({
params: { id: post.id },
}));
// `fallback: false` означает, что для ошибки 404 используется другой маршрут
return {
paths,
fallback: false,
};
}
На странице pages/posts/[id].js
также должна экспортироваться функция getStaticProps
для получения данных поста с указанным id
:
export default function Post({ post }) {
// ...
}
export async function getStaticPaths() {
// ...
}
export async function getStaticProps({ params }) {
const post = await (
await fetch(`https://example.com/posts/${params.id}`)
).json();
return {
props: {
post,
},
};
}
SSR¶
Для обработки рендеринга страницы на стороне сервера из файла должна экспортироваться асинхронная функция getServerSideProps
. Данная функция будет вызываться при каждом запросе страницы.
function Page({ data }) {
// ...
}
export async function getServerSideProps() {
const data = await (
await fetch('https://example.com/data')
)?.json();
return {
props: {
data,
},
};
}