Очень хорошая и практичная статья про утечки памяти в Next.js. Чел рассмотрел 3 утечки (которые уже исправлены — поэтому обновляйтесь) и то, как их правильно диагностировать.
Если ваше приложение использует Next.js версии между 15.5 и 16.2, то в них есть 3 задокументированных утечки памяти. Вот как их диагностировать:
1. Если утечка медленная и коррелирует с количеством уникальных урлов, которые обслужило приложение, то это утечка Router LRU-кеша
2. Если утечка пропорциональна трафику, то вполне вероятно это утечка дерева рендеринга
3. Если утечка не плавная, а ступеньками, а запросы обрабатываются через middleware, то это утечка айдишников таймаутов
Немного подробнее про каждую утечку.
№1: У роутера в Next.js есть LRU-кеш, и его размер ограничен одним мегабайтом. Но размер определяется некорректно. Собственно сами урлы и не учитываются, что даёт возможность для утечки на сотни мегабайт. Банально любой бот, который перебирает урлы, вызовет эту утечку. Если не можете обновиться — отфильтровывайте урлы до их обработки роутером Next.js.
№2: Дерево RSC-рендера не освобождается, если клиент разорвал соединение. Утечка может достигать 2 МБ на 1 отменённый запрос (что вообще-то нехило).
№3: У middleware отдельный
TimeoutsManager, который хранит id таймаутов. id отпускается только если явно вызвать clearTimeout.А дальше интересный личный кейс автора. У него приложение крутилось как serverless на Vercel, поэтому вместо OOM он получал
504 FUNCTION_INVOCATION_TIMEOUT на tag-страницах блога.Автор провёл расследование. Сначала подозревал рендер MDX, но оказалось, что он достаточно быстрый — до 100 мс. Оказалось, что причина в функции, которая резолвила slug для страницы. Чтобы зарезолвить один единственный slug, функция грузила и парсила все посты для каждого слага, что давало квадратичную сложность и выливалось в 18 тысяч чтений с диска и 30 секунд на рендер.
Фикс простой: вместо парсинга всех постов на каждый запрос — распарсить единожды и сложить в кеш на инстанс. Скорость работы после исправления:
-
next build: ~17.5 мин → 34 сек- prerender поста: ~32 сек → ~1.6 сек
- on-demand tag page: 504 → ~134 мс
Для поиска утечек автор собрал CLI `next-leak`, который автоматизирует диагностику.
Также отдельно отмечу, что у автора очень красиво задизайнен блог. Не знаю, готовая ли это тема или он сам собрал — но выглядит очень красиво.
https://xabierlameiro.com/blog/nextjs/nextjs-memory-leak-in-production
#development #nextjs #memory #performance #debugging