«use client» по привычке
Самая частая ошибка — пометить клиентом всё подряд и убить весь смысл App Router. `'use client'` нужен только там, где есть хуки, обработчики событий или браузерные API. Граница клиента должна быть как можно ниже по дереву — данные грузим там, где они используются, а не на уровне страницы.
async params и перевёрнутый кэш
В Next.js 15 `params` и `searchParams` стали асинхронными: забыл `await` — получил undefined в динамическом роуте. И дефолты кэша перевернулись — данные теперь свежие по умолчанию. Если данные «протухали» на 14-й версии и всегда свежие на 15-й — это оно. Задавайте стратегию кэша явно, не надейтесь на дефолт.
// Next 15: params — это Promise
export default async function Page({
params,
}: { params: Promise<{ slug: string }> }) {
const { slug } = await params; // забыл await → undefined
const data = await fetch(url, {
next: { revalidate: 3600 }, // кэш задаём явно
});
}Сериализация: не передавай функции и Date
Если отправить из серверного компонента в клиентский функцию, объект Date или инстанс класса — получите hydration mismatch. Через границу едут только простые данные. Дату — строкой ISO, логику — на сервере.
- 01.Граница клиента — как можно ниже по дереву
- 02.Всегда await params и searchParams
- 03.Стратегия кэша — явно, на каждом fetch
- 04.Через границу — только сериализуемые данные
«RSC не делают приложение быстрым сами по себе. Они дают место, куда НЕ класть JavaScript.»
Что бы сделали иначе
Мы мигрировали проект на 15-ю в середине разработки и потеряли 3 дня на сюрпризы с кэшем. Надо было сдать релиз на стабильной версии, а апгрейд делать отдельным этапом — не на дедлайне.