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

Режим предпросмотра

Представим, что у нас есть статическая страница, которая использует getStaticProps и/или getStaticPaths и рендерится во время сборки. Например, это страница отдельного поста.
Теперь представим, что у нас есть система управления контентом, в которой мы пишем новый пост. Хотелось бы иметь возможность увидеть, как этот пост в итоге будет выглядеть - то есть иметь превью.
То есть мы хотим использовать статическую страничку поста, но динамически, передав ей текущий черновик.
Next такое может, об этом вот здесь: https://nextjs.org/docs/advanced-features/preview-mode

Автоматическая статическая оптимизация (оптимизация статических страниц)

Этот раздел про то, что Next автоматически генерирует html для страниц, которые не используют getServerSideProps.
Тут важно помнить, что если это, например, динамический роут, то страница при рендеринге не получит параметры роута, а после гидратации получит и перерендерится.
Отследить, готовы ли параметры роута, можно, проверив поле router.isReady (хук useRouter).
Подробнее: https://nextjs.org/docs/advanced-features/automatic-static-optimization

Директория src

Фронтендерам привычно использовать для исходников директорию src. В Next же вместо этого мы размещаем все в корне проекта. При желании, можно использовать src, фреймворк это поддерживает. Тогда страницы должны лежать в папке src/pages.
Файлы конфигурации и директория public при этом должны оставаться в корне проекта.
https://nextjs.org/docs/advanced-features/src-directory

Непрерывная интеграция и кэширование сборок

Это о том, как настроить CI workflow, чтобы кэш сохранялся между сборками: https://nextjs.org/docs/advanced-features/ci-build-caching

Multi zones

Словом zone (зона?) обозначается отдельное развертывание (деплой) Next-приложения. Таких зон может быть несколько и они могут объединяться в одно приложение.
Не совсем пока понятно, что это и для чего.
Подробнее: https://nextjs.org/docs/advanced-features/multi-zones

Измерение производительности

Next.js самостоятельно собирает все метрики производительности приложения. Чтобы использовать их, нужно из файла pages/_app.js экспортировать функцию reportWebVitals. Она будет вызываться для каждой измеренной метрики.
Подробнее: https://nextjs.org/docs/advanced-features/measuring-performance

Трассировка выходных файлов

Вроде как позволяет создать сжатую версию приложения со всеми зависимостями в отдельной папке, которую можно развернуть без node_modules.

Подробнее: https://nextjs.org/docs/advanced-features/output-file-tracing

#nextjs #документация
👍5
Next.js. Middleware

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

Создать такой миддлвар очень просто - нужно просто сделать файлик middleware.js и положить его в корень проекта (рядом с папкой pages). Из этого файла нужно экспортировать функцию middleware.

В качестве параметра функция принимает объект запроса и может либо вернуть объект ответа (NextResponse), либо куда-нибудь перенаправить. Если ничего не вернуть, то запрос выполнится без всяких изменений, как будто и нет никакого миддлвара.

Соответственно, объект ответа можно сформировать как угодно, проставить ему любые заголовки и т. д.

В миддлваре, например, удобно проводить проверку на аутентификацию юзера - и если ее нет, то возвращать ошибку или перенаправлять на страничку логина.

Думаю, к этой теме мы еще вернемся, звучит она интересно.

Подробнее: https://nextjs.org/docs/advanced-features/middleware

#nextjs #документация
🔥3👍1
Next.js. Обработка ошибок

Статья в документации: https://nextjs.org/docs/advanced-features/error-handling

Тут ничего особо интересного:

development mode

В режиме разработки приложение будет просто выбрасывать модалку с описанием ошибки.

Ошибки сервера

Если ошибка произошла на стороне сервера, пользователь увидит страницу 500 (или 404, если нужная страница не найдена).

Ошибка клиента

Для обработки клиентских ошибок нам предлагают использовать предохранитель ErrorBoundary. Импортируем его в _app.js и оборачиваем в него компонент страницы.

#nextjs #документация
👍4
Next.js. Индикатор загрузки страницы

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

По мотивам статьи How To Handle Loading Between Page Changes in Next.js :) (англ.) https://medium.com/@remoteupskill/how-to-manage-loading-elegantly-in-your-next-js-application-5debbfb4cace

Нам потребуется каким-то образом отслеживать начало и окончание перехода между страницами. Логично, что для этого пригодится объект роутера, который можно получить из хука useRouter. У роутера есть поле router.events - это эмиттер событий. Нам нужно подписаться на событие начала перехода (routeChangeStart) и событие окончания перехода (routeChangeComplete).

Инкапсулируем логику отслеживания в виде хука useLoading. Он будет возвращать состояние isLoading, которое будет меняться в зависимости от событий роутера.

Подписка происходит внутри хука useEffect, не забываем также про сброс эффекта.

import { useEffect, useState } from "react";
import { useRouter } from "next/router";

function useLoading() {
const router = useRouter();
const [isLoading, setLoading] = useState(false);

useEffect(function() {
function onStart() {
setLoading(true);
}
function onComplete() {
setLoading(false);
}

router.events.on("routeChangeStart", onStart);
router.events.on("routeChangeComplete", onComplete);

return () => {
router.events.off("routeChangeStart", onStart);
router.events.off("routeChangeComplete", onComplete);
};
}, [router]);

return isLoading;
}


Теперь можно создать компонент спиннера и вывести/скрыть необходимый индикатор в зависимости от состояния isLoading.

const isLoading = useLoading();

if (isLoading) return "Loading...";

return null;


Демо: https://codesandbox.io/p/sandbox/next-page-loader-react-junior-r4n00r?file=%2Fhooks%2FuseLoading.ts&selection=%5B%7B%22endColumn%22%3A7%2C%22endLineNumber%22%3A11%2C%22startColumn%22%3A7%2C%22startLineNumber%22%3A11%7D%5D

В демо есть две странички - Home и About. Для каждой добавлена искусственная задержка загрузки (2 секунды) в getServerSideProps, чтобы виден был индикатор.

Отдельного компонента индикатора нет, он размещен вместе с прочей общей разметкой в файле _app.tsx.

#ссылки #nextjs #примерыкода
👍2🔥2
Стоит ли использовать Redux в Next.js-приложении?

Статья (англ.): https://javascript.plainenglish.io/should-you-use-redux-in-next-js-5e57201c34da

Автор статьи считает, что нам нужно отказаться от Redux в Next.

Причина #1: В нем нет особого смысла, так как благодаря серверному рендерингу мы сразу же, еще до рендеринга страницы, получаем нужные данные.

Причина #2: У Redux есть ряд альтернатив - более легких, нативных и удобных. Например, React Context или Local Storage. В большинстве случаев их функциональности более чем достаточно. Для более сложных сценариев, например, для загрузки данных на клиенте есть библиотеки вроде swr или react-query.

Причина #3: Redux внутри Next сложно хорошо настроить и оптимизировать.

#nextjs #ссылки #redux
👍2
Next.js Middleware: Как оно работает и 5 примеров использования

Статья (англ.): https://javascript.plainenglish.io/next-js-middleware-how-it-works-and-5-real-use-cases-cfacbeb810c9

Про миддлвары в Next мы уже начинали говорить вот тут: https://yangx.top/react_junior/504

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

В качестве параметра она получает запрос пользователя (request) и может редиректнуть его, если необходимо.

import { NextResponse } from 'next/server';

export function middleware(request) {
// redirect
return NextResponse.redirect(new URL('new_url', request.url));

// rewrite (сохранить урл, но показать другую страницу)
const url = request.nextUrl.clone();
url.pathname = 'new_url';
return NextResponse.rewrite(url);

// ничего не изменять
return NextResponse.next();
}

Из того же файла можно экспортировать переменную config, в которой, например, можно определить для каких урлов применяется миддлвар (config.matcher).

export const config = {
matcher: '/dashboard/:path*'
}


В статье разбирается базовый функционал миддлвара, а также несколько кейсов его использования:

- аутентификация: получаем данные авторизации из заголовка запроса (request.headers.get('authorization')), если они не совпадают с нужными, переадресуем на страницу авторизации.

- страница "Сайт находится в разработке": если в урле есть секретный параметр, то показываем реальную страницу, если нет - переадресуем всех на страницу "В разработке".

- персонализация: делим пользователей на группы, по запросу определяем, к какой группе принадлежит этот конкретный пользователь (например, по кукам), и отправляем его на соответствующую страницу.

- блокировка ботов: по заголовку request.headers['user-agent'] определяем, является ли пользователь ботом.

#nextjs #ссылки
👍3
Как настроить Redux в NextJS

Совсем недавно мы видели мнение, что Redux в Next.js использовать не стоит: https://yangx.top/c/1218235935/551

Но если вам все-таки хочется, то вот руководство по настройке (англ.): https://medium.com/how-to-react/how-to-setup-redux-in-nextjs-5bce0d82b8de

Выглядит не особо сложно. Помимо обычных настроек Redux нам понадобится еще функция createWrapper из пакета next-redux-wrapper.

const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);

const wrapper = createWrapper(function() {
return store;
});


Теперь нужно обернуть приложение в провайдер хранилища. Сделать это лучше всего в файле _app.js. В провайдер передаем store.

А чтобы все работало, нужно использовать компонент высшего порядка wrapper.withRedux.

import { Provider } from "react-redux";

function MyApp({ Component, pageProps }) {
return (
Provider store={store}
Component {...pageProps}
)
}

export default wrapper.withRedux(MyApp);


Вот и все, теперь можно пользоваться плюшками Redux.

#nextjs #redux #статьи
👍3