React Junior
207 subscribers
37 photos
462 links
Изучение React с нуля
加入频道
Next.js. Мета-данные страницы

Весь этот серверный рендеринг затевался для того, чтобы сделать наши страницы лучше в плане SEO. Давайте же этим сео и займемся.

Next предоставляет компонент Head, в который можно поместить любые теги, которые должны быть в секции head страницы (title, meta-теги). Размещать этот компонент можно в любом месте страницы.

#серверныйрендеринг #nextjs
🔥3👍2
Компоненты/лейауты, которые переиспользуются на разных страницах, нужно вынести за пределы папки pages, так как в pages должны лежать именно страницы.

#nextjs #серверныйрендеринг #примерыкода
👍3🔥2
Next.js. Файл pages/_document

Есть возможность изменить базовую HTML-структуру страницы, для этого нужно создать свой файл pages/_document.tsx. Компонент в этом файле может по своему усмотрению разместить компоненты Html, Head, Main и NextScript (импортируются из next/document).

- Html - корневой узел документа.
- Head - это head, но не тот же самый, который мы уже встречали в next/head. Этот head (next/document) предназначен для размещения кода, общего для всех страниц. Тот head (next/head) - для размещения отличающегося кода, например, title, на отдельных страницах.
- Внутрь Main будет вставляться активная страница. Все, что находится вне Main, не будет инициализировано, поэтому сюда не нужно добавлять какую-то логику.
- NextScript - это скрипты, которые нужны для работы Next.js.

Компонентам можно добавлять атрибуты (например, lang).

Страница в документации (англ.): https://nextjs.org/docs/advanced-features/custom-document

#nextjs #серверныйрендеринг
👍4🔥1
Next.js. Файл pages/_app

В Next.js мы можем перехватить контроль над инициализацией активной страницы. Например, это полезно для сохранения каких-то данных между переходами или, наоборот, для передачи дополнительных данных на страницу.

Кроме того, именно в этом месте мы можем добавить глобальные стили для приложения.

UPD: также, здесь, кажется, хорошее место для размещения провайдеров глобальных контекстов.

Для этого создаем файл pages/_app.tsx.

В базовом варианте он выглядит очень просто:

- принимает пропсы Component (компонент активной страницы) и pageProps
- и просто рендерит этот компонент с этими пропсами.

Страница в документации (англ.): https://nextjs.org/docs/advanced-features/custom-app

#nextjs #серверныйрендеринг
👍6
Next.js. Стили

Что по стилям?

1. Если нам нужны какие-то глобальные стили, то можно импортировать .css-файлы в наш кастомный компонент App (файл pages/_app.tsx). Но такой трюк пройдет только здесь. При попытке импортировать .css-файл с глобальными стилями на какую-нибудь страницу или в компонент, вылетит ошибка:

Global CSS cannot be imported from files other than your Custom App. Due to the Global nature of stylesheets, and to avoid conflicts, Please move all first-party global CSS imports to pages/_app.js. Or convert the import to Component-Level CSS (CSS Modules).

2. Однако внутри компонентов/страниц мы можем импортировать стили сторонних библиотек (из node_modules).

3. Если необходимо импортировать свои стили в компонент, нам предлагают пользоваться CSS-модулями (разбирали их здесь).

4. Можно использовать препроцессоры, например, SCSS, но понадобится установить пакет sass. Поддерживается даже прямой импорт и использование SASS-переменных в файлах компонентов.

5. Документация уверяет, что поддерживаются любые решения CSS-in-JS. Действительно, со Styled Components проблем не возникло. Глобальные стили (createGlobalStyles) следует размещать в файле _app.tsx.

6. Также нам предлагают использовать styled-jsx, который поддерживается из коробки. При этом можно писать стили прямо в JSX-разметке, внутри тега style как обычный CSS (документация тут).

#nextjs #серверныйрендеринг #стили
👍2🔥1
Нашелся старый пост с субъективным сравнением разных способов стилизации React-приложений: https://yangx.top/react_junior/229

Надо признать, что с тех пор мои предпочтения немного изменились и в большинстве своих проектов я использую Styled Components. Синтаксис стал привычнее, и в целом это решение весьма удобное. НО! - только если стилей мало. Для больших простыней по-прежнему предпочитаю модули + препроцессоры.

#стили
👍2
Next.js. Страница 404

По умолчанию Next предлагает свою страницу 404 для несуществующих роутов, но мы можем ее заменить. Для этого нужно просто создать файл pages/404.tsx и вернуть из него нужный компонент.

Демо-проект: https://codesandbox.io/p/sandbox/stupefied-sutherland-r0xd40?selection=%5B%7B%22endColumn%22%3A2%2C%22endLineNumber%22%3A3%2C%22startColumn%22%3A2%2C%22startLineNumber%22%3A3%7D%5D&file=%2Fpages%2F404.tsx

#nextjs #серверныйрендеринг
👍3🔥1
Next.js. Получение данных на сервере

Переходим к самому интересному. Как сделать так, чтобы на клиент приходила страница уже с данными. Например, список постов? Нужно запросить данные еще на сервере и уже с ними отрендерить компонент, чтобы клиент получил готовый HTML.

Судя по документации у Next есть минимум три разных способа это сделать. В курсе подробно разбирается метод getInitialProps, поэтому начнем с него, хотя, кажется, что это не самый лучший подход.

Компоненту, которому нужны данные, нужно добавить статический метод getInitialProps. Сервер использует его при рендере страницы.

Метод должен вернуть объект, который будет передан в компонент как пропсы.

Получим например, список постов для страницы posts.tsx:

export default function Posts({ posts }) {
//..
}

Posts.getInitialProps = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await response.json();

return {
posts
}
}


Работает это вполне логично:

1. Сервер получает запрос к странице Posts.
2. Видит, что у компонента этой страницы есть метод getInitialProps и выполняет его.
3. То, что получилось на выходе, передается в сам компонент в виде пропсов.
4. Компонент рендерится в HTML-код.
5. Клиент получает готовую страницу (уже с данными).

Звучит прям ну очень знакомо, да? Классический серверный рендеринг.

Проблема в том, что пока выполняется запрос, клиент ждет с пустой страницей.

#nextjs #серверныйрендеринг
🔥3👍2
Next.js. getInitialProps

Метод getInitialProps вызывает каждый раз при переходе на страницу. И при первом запросе, когда сервер рендерит нам страницу, и при каждом переходе на клиенте, в режиме SPA.

То есть, мы вводим в адресную строку урл localhost/posts - сервер выполняет запрос для получения нужных пропсов - страница загружается уже с данными.

Затем мы на клиенте переходим на главную и обратно на /posts - метод снова вызывается для получения пропсов. При этом, если метод работает долго, переход будет задерживаться.

Можно использовать такой подход:

- если метод вызывается на сервере (для первичного рендеринга приложения), то оставить все как есть
- если метод вызывается на клиенте (при переходе с другой страницы SPA), не вызывать getInitialProps. По сути мы быстро отрендерим пустой компонент (без пропсов), а уже потом (в хуке useEffect) загрузим нужные данные, показывая в это время понятный лоадер.

Звучит как дублирование логики, но ок - как нам понять, где именно вызывается метод?

getInitialProps при вызове получает один аргумент - контекст вызова. В нем куча данных, в том числе объекты req и res - HTTP-запрос и HTTP-ответ соответственно. Они приходят только если вызов произошел на сервере, то есть по их наличию можно ориентироваться.

export default function Posts({ posts }) {
const [postsList, setPostsList] = useState(posts);
useEffect(function() {
if (!posts) {
// загрузить посты на клиенте
}
})

if (!posts) {
// вернуть лоадер
}

// вернуть страницу с постами
}

Posts.getInitialProps = async ({ req }) => {
if (!req) {
return { posts: null }
}

const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await response.json();

return {
posts
}
}


#nextjs #серверныйрендеринг
👍6
Next.js. getInitialProps - параметры

Тот же подход можно использовать для предварительной загрузки поста на сервере - страница post/[id]. Но тут нам нужно знать значение динамического параметра.

Получить его можно из того же объекта контекста, который передается в метод getInitialProps.

export default SinglePost({ post }) => {
// ...
};

SinglePost.getInitialProps = async ({ query }) => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts/${query.id}`
);
const post = await response.json();
return {
post,
};
};


#nextjs #серверныйрендеринг
👍4
Next.js + TypeScript

Для описания страниц в Next-приложении нам потребуется тип NextPage (импортируется из пакета next). Это дженерик, который принимает тип пропсов компонента.

#nextjs #серверныйрендеринг #typescript
👍2🔥1
Next.js. getServerSideProps

Вероятно, вместо getInitialProps лучше использовать getServerSideProps.

Идея такая же, но getServerSideProps работает ТОЛЬКО на сервере (не запускается при переходе между страницами на клиенте в режиме SPA. То есть данные запрашиваются один раз и переиспользуются при загрузке страницы любым способом.

Разница:

- getInitialProps это статический метод компонента, а getServerSideProps просто функция, которую нужно импортировать из файла страницы.
- getServerSideProps должна вернуть объект с полем props.
- так как getServerSideProps работает только на сервере, нам не требуется проверять наличие req.

#nextjs #серверныйрендеринг
👍4🔥1
Forwarded from Cat in Web
Все виды Server-side рендеринга в NextJS: SSR, CSR, SSG, ISR

Видео (рус.): https://www.youtube.com/watch?v=xg-lajRmCco

Видео на 15 минут с обзором различных способов рендеринга в современном фронтенде. Примеры в основном на Next.js (React).

CSR - Client Side Rendering

Самая привычная нам форма работы, при которой все запросы исходят с клиента и DOM полностью формируется на клиенте.
Из минусов:
- долгая первая загрузка бандла (потом его можно закешировать), при которой пользователь видит только пустую страницу
- плохая SEO, так как поисковик тоже видит пустую страницу

SSR - Server Side Rendering

В этом подходе сервер самостоятельно рендерит страницу (при необходимости получает для нее данные) и отдает на клиент уже готовый HTML, который затем проходит гидратацию и становится нормальным SPA. Это SEO friendly, тратит меньше ресурсов устройства, но требуется время для подготовки страницы на сервере.

SSG - Static Site Generation

Другой способ - отрендерить все страницы сразу же, во время сборки проекта, не дожидаясь запросов пользователя. Готовые HTML складываются на сервере и при запросе сразу отдаются без затрат времени на подготовку. Не подходит для контента который должен быть актуальным. Также сомнительный способ, если на вашем сайте тысячи страниц (например, большой блог).

ISR - Incremental Static Regeneration

Та же SSG, но с возможностью обновить сгенерированные страницы по таймеру.

#serversiderendering #nextjs #ssr #ssg #isr
👍4
Next.js. Ошибка гидратации

Иногда выскакивает ошибка типа:

next-dev.js?3515:20 Warning: Prop `className` did not match. Server: "sc-ipEyDJ SbBBO" Client: "sc-gswNZR cjWWhU"


И в конце сообщения ссылка https://nextjs.org/docs/messages/react-hydration-error.

Это ошибка гидратации, когда на сервере рендерится одно, а при первом рендере в браузере - другое. Она может возникать, если мы используем в коде условия, которые по разному вычисляются на сервере и на клиенте. Или при невалидной HTML-разметке.

В моем случае ошибка связана с библиотекой Styled Components: рендерятся разные классы для элемента.

Чтобы такого не было, нужно правильно настроить проект. Обязательно нужно добавить файл pages/_document и плагин babel-plugin-styled-components (файл .babelrc описан здесь https://dev.to/aprietof/nextjs--styled-components-the-really-simple-guide----101c).

Для Next.js 12.1+ достаточно добавить опцию в конфиг next.config.js. Описано здесь: https://nextjs.org/docs/advanced-features/compiler#styled-components

#nextjs #серверныйрендеринг #ошибки #стили #важно
👍1🔥1
Forwarded from Cat in Web
Roadmap для React-разработчика

https://roadmap.sh/react

От базовых концепций - компонентов и хуков - до тестирования и фреймворков. Полезная штука для представления современной React-экосистемы.

#react #roadmap
👍2
С Наступающим! 🎄
Интересных проектов, профессиональных достижений и прекрасного настроения в Новом году! Ура! 🎇
👍5🎉4🍾1🎄1
Forwarded from Cat in Web
12 хуков React, которые должен знать каждый разработчик

Статья (рус.): https://nuancesprog.ru/p/16589/

В статье есть реально классные библиотеки, которые стоит взять на заметку.

1. react-swipeable - для обработки свайпов
2. use-resize-observer - позволяет изменять размеры элемента и измерять их
3. formik - для всей рутины с формами (валидация, посещенные поля и т.д.)
4. use-debounce - позволяет отслеживать какие-то изменения с задержкой для увеличения производительности
5. use-isomorphic-layout-effect - нужен для SSR, так как на сервере нельзя использовать хук useLayoutEffect
6. swr - библиотека для получения данных (stale-while-revalidate)
7. react-hotkeys-hook - для работы с горячими клавишами
8. @use-gesture/react - обработка жестов и различных событий
9. react-script-hook - для динамической загрузки внешних скриптов
10. react-scroll-parallax - для реализации параллакса при скроллинге
11. react-storage-hooks - для синхронизации состояния приложения с хранилищем (`localStorage`/`sessionStorage`)
12. @chakra-ui/color-mode - поддержка светлого и темного режимов

#react #hooks #библиотеки
👍3
Next.js. SSG

Сегодня забежим вперед и глянем одним глазом на SSG в Next.js - Static Site Generation.
Сразу предупреждаю: делается это только из неутолимого интереса и больше наощупь, чем по проверенным рецептам.

Итак, предполагается, что при сборке все странички сразу должны отрендериться с начальными данными и появиться в проекте в виде готовых HTML-документов.

Вместо getServerSideProps нужно использовать функцию getStaticProps (сигнатура у нее практически такая же).
Нужно внести изменения на страницах posts и post/[id].

С posts никаких проблем не возникло, а вот с динамическим роутом все сложнее. Там мы вытаскиваем id поста из параметра context.query, но при статической генерации никакого query у нас не будет. И как вообще понять, какие у нас есть посты и какие страницы для них генерировать?

Для этого есть еще одна функция getStaticPaths, которая как раз и должна вернуть нам все необходимые урлы. Их нужно вернуть в поле paths (массив):

export const getStaticPaths: GetStaticPaths = async function() {
const paths = [
{ id: '1' },
{ id: '2' },
{ id: '3' }
];

return {
paths,
fallback: false,
};
};


Функция асинхронная, так что внутри нее можно выполнить, например, запрос к базе данных и получить айдишники всех существующих постов.

Теперь в функцию getStaticProps нам будут приходить параметры для каждого поста. Их можно получить из поля params.

export const getStaticProps: GetStaticProps = async function(context) {
const { id } = context.params;
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
const post = await response.json();
return {
props: {
post
}
}
}


Теперь запускаем команду npm run build и смотрим в папку .next/server/pages. Тут можно найти все наши странички уже в виде HTML. Кроме того, для каждой страницы генерируется еще JSON-файл с данными.

#nextjs #серверныйрендеринг #примерыкода
👍3🔥1
Next.js. API

Next позволяет легко создавать эндпоинты API.

Создаем в папке pages новую папку api, а в ней - файлы для эндпоинтов.
Из каждого файла нужно по дефолту экспортировать функцию, которая будет обрабатывать запрос.

export default function echo(req, res) {
res.status(200).json({
message: req.query.message,
});
}


Обратиться к нему можно по урлу /api/echo?message=SomeText.

В папке api также можно создавать роуты с динамической частью: pages/api/[id].ts. Динамический параметр можно получить из req.query.id.

#nextjs #серверныйрендеринг
👍3🔥2