Перейти к содержанию

Страницы (Pages)

Страница — это компонент React, который экспортируется из файла с расширением .js, .jsx, .ts или .tsx, находящегося в директории pages. Каждая страница ассоциируется с маршрутом (роутом) по названию. Например, страница pages/about.js будет доступна по адресу /about. Обратите внимание, что страница должна экспортироваться по умолчанию (export default):

1
2
3
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

Генерироваться могут как страницы с данными, так и страницы без данных.

Без данных

1
2
3
export default function About() {
  return <div>О нас</div>;
}

Существует 2 возможных сценария, при которых может потребоваться генерация статической страницы с данными:

  1. Контент страницы зависит от внешних данных: используется getStaticProps
  2. Пути (paths) страницы зависят от внешних данных: используется getStaticPaths (как правило, совместно с getStaticProps)

Контент страницы зависит от внешних данных

Предположим, что страница блога получает список постов от CMS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// TODO: запрос `posts`

export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

Для получения данных, необходимых для предварительного рендеринга, из файла должна экспортироваться асинхронная функция getStaticProps. Данная функция вызывается во время сборки и позволяет передавать полученные данные странице в виде props:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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. Данная функция вызывается во время сборки и позволяет определить пути для пререндеринга:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
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. Данная функция будет вызываться при каждом запросе страницы.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
function Page({ data }) {
  // ...
}

export async function getServerSideProps() {
  const data = await (
    await fetch('https://example.com/data')
  )?.json();

  return {
    props: {
      data,
    },
  };
}

Комментарии