+7 (495) 801-60-42

В прошлом месяце команда NextJS показали предварительный обзор новых инструментов в Next.js 16.3, которые делают навигацию между страницами мгновенной в приложениях, построенных на React Server Components.

Они начали внедрять эти инструменты в v0 — full-stack платформе Vercel для разработки с помощью кода — и поделились графиком, который показывает, насколько быстрее стала навигация в продакшене.

График: время навигации между страницами в v0 в продакшене.

Что особенно впечатляет: этих результатов удалось добиться с помощью coding agent, который использовал новый Skill, чтобы писать падающие тесты, исправлять медленные переходы и проверять каждый маршрут.

2026-08-12 11.19.49.jpg

Мы разберём, как такие тесты могут проверять медленную навигацию и как работает Skill.

Но сначала посмотрим, какой подход использует Next.js 16.3, чтобы приложения вроде v0 ощущались быстрыми и отзывчивыми — без необходимости переносить получение данных или рендеринг на клиент.

Предрендеринг для динамических приложений

Раньше Next.js предлагал два основных инструмента, чтобы обеспечить мгновенную навигацию в приложении.

Можно было статически предрендерить страницы во время сборки. Но это непрактично для динамических приложений с персональными данными.

Или можно было помечать ссылки как полностью предварительно загружаемые через prefetch. Но это может быть дорого с точки зрения ресурсов и создавать повышенную нагрузку на серверы.

В итоге у динамических персонализированных приложений вроде v0 не было хорошей стратегии для достижения мгновенной навигации.

Next.js 16.3 решает эту проблему: теперь динамический контент можно предрендерить в процессе того, как пользователи перемещаются по приложению, и полностью кэшировать этот контент в браузере.

Компоненты, которые рендерят динамический персонализированный интерфейс, теперь могут либо определять состояние загрузки через Suspense, либо помечать часть интерфейса как доступную для предрендеринга с помощью 'use cache'.

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

Это первый случай, когда Next.js дал динамическим приложениям возможность использовать технологию, лежащую в основе Partial Prerendering.

Вот что сказал об этом инженер, работающий над v0:

"Да, большое спасибо @jude.gao за то, что возглавил эту работу. Для блога или кейс-стади, думаю, было бы хорошо ясно объяснить, что instant не равно PPR, и что этого намного проще достичь. Даже я, работая здесь, думал, что достижение instant потребует гораздо больше усилий, чем оказалось в итоге, отчасти потому, что я предполагал, что нам придётся проделать работу, сравнимую с внедрением статического PPR."
"Итак, динамические приложения могут частично предрендерить страницы во время выполнения. Именно так они могут добиться мгновенной навигации, при этом отправляя в браузер минимум кода."
"Теперь вы можете подумать, что единственный способ проверить, действительно ли навигация стала мгновенной, — это отрефакторить код, запустить приложение и вручную кликнуть по ссылке, чтобы убедиться самому."
"Но одна из самых новых и необычных возможностей Next.js 16.3 заключается в том, что он поставляется с новым примитивом, который позволяет вам или агенту понять, что маршрут действительно стал мгновенным."
"Благодаря этому новому примитиву агенты идеально подходят для того, чтобы самостоятельно добиваться мгновенной навигации в уже существующем приложении."
"Именно так мы и сделали v0 мгновенным."

Использование циклов, чтобы сделать v0 мгновенным

Чтобы внедрить эти новые возможности в v0, команда NextJS использовали агента, работающего в цикле.

Для каждой медленной навигации он:

  • писал падающий тест;
  • применял исправление;
  • запускал тест снова;
  • повторял процесс, пока тест не начинал проходить.

Чтобы такой цикл мог выполняться самостоятельно, ему были нужны три вещи.

Проверяемая цель.

Падающий тест, который завершает цикл, когда начинает проходить.

Ограничители и направляющие.

Skill с проверенными паттернами, которые приближают код к цели.

Реальная обратная связь.

Продакшен-метрики, подтверждающие, что успешный цикл дал ожидаемый эффект.

Схематично процесс выглядел так:

2026-08-12 11.19.20.jpg

Самая сложная часть этого цикла — написать падающий тест для чего-то размытого вроде: «Убедиться, что эта навигация мгновенная».

К счастью, в Next.js 16.3 было именно то, что нам нужно.

Тест для «Скорости»

Next.js 16.3 включает тестовый helper instant() для Playwright.

Этот helper позволяет писать тесты, которые приостанавливают навигацию и проверяют, какие части интерфейса мгновенно видны пользователю — без каких-либо сетевых запросов.

Файл e2e/navigation.spec.ts:

2026-08-12 11.24.05.jpg

Если ожидаемый контент был заблокирован сетью, тест падал.

С этим инструментом мы были готовы запустить цикл.

Запуск цикла на v0

Теперь у команды было всё необходимое, чтобы исправить медленную навигацию в v0.

Вот как выглядел их процесс.

Собрать критически важные пользовательские сценарии, которые работают медленно

Команда NextJS знали, что некоторые важные переходы в v0 были медленными:

  1. переход к New Chat с главной страницы;
  2. навигация по настройкам;
  3. просмотр профиля.

Поэтому они сфокусировались именно на них.

Next.js 16.3 также включает новую функцию Instant Insights, которая во время разработки автоматически показывает все маршруты, которые не являются мгновенными.

Написать падающие тесты

Агент написал падающий тест для каждой навигации, используя helper instant().

Сам по себе агент со Skill старается определить, какая часть интерфейса должна быть видна мгновенно. Но вы также можете направить его и указать конкретные элементы, которые нужно включить в проверку. Например, метку Chats на странице нового чата в v0.

Рефакторить, пока все тесты не пройдут

Агент использовал паттерны из Skill, чтобы применять идиоматичные изменения к нашему Next.js-коду, и продолжал работу, пока каждый тест не начинал проходить.

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

Закоммитить изменения и тесты

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

Поэтому мы оставили их в проекте, чтобы они запускались вместе с остальным набором тестов в CI.

Но как выглядели сами изменения?

Во многих случаях, чтобы разблокировать медленную навигацию, было достаточно переместить доступ к динамическим данным ниже границы Suspense и позволить остальному содержимому страницы попасть в shell.

Вот пример.

2026-08-12 11.30.21.jpg

В других случаях требовались более крупные рефакторинги. Например, нужно было вынести блокирующую зависимость из root layout и перенести её в те компоненты, которые действительно её использовали.

Но независимо от того, какие изменения были нужны, агент смог применить современные лучшие практики Next.js, используя паттерны, включённые в Skill.

Быстро — навсегда

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

В результате мы получили 16 новых тестов, которые зафиксировали эти результаты в нашем тестовом наборе.

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

Почему фреймворки важны в эпоху агентов

Каждый, кто разрабатывал с помощью агентов, знает, насколько важны детерминированные тесты.

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

Но некоторые аспекты поведения приложения сложно тестировать.

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

Тестовый helper instant() — новый пример того, как такие более размытые аспекты качественного приложения можно превратить во что-то детерминированное.

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

Мы считаем, что такой верификатор — одна из самых полезных вещей, которые фреймворк может предоставить в эпоху агентов. И мы планируем продолжать добавлять больше подобных инструментов в Next.js.

Это также доказывает, что даже в мире, где агенты пишут значительную часть нашего кода, фреймворки всё ещё имеют значение.

Агент может написать любой код, который захочет. Но задача фреймворка — направлять и ограничивать его так, чтобы в итоге получались более качественные интерфейсы, чем если бы агент действовал полностью самостоятельно.

Именно к такому будущему мы движемся с Next.js.