Next.js 15.3: Turbopack в продакшне, instrumentation-client.ts и навигационные хуки, которые решают реальные боли
Turbopack Builds (alpha)
Исправление главного недостатка (в моем представлении) turbopack - теперь он доступен и и в production
Раньше не было смысла держать два разных бандлера: один для dev, другой для боевого окружения. С версии 15.3 всё меняется: появилась альфа-команда
next build --turbopack
Команда nextjs пока что не рекомендует использовать это для критически важных приложений, но для новых проектов я уже перехожу на него сам и советую задуматься о миграции. Это действительно ускоряет сборку, уменьшает размер бандла и повышает производительность.
Добавлен новый файл instrumentation-client.js|ts
Он позволяет выполнять скрипты ДО того, как начнёт выполняться код веб-приложения. Его необходимо располагать в root
папке проекта или app/pages
директориях.
Основные кейсы: интеграци инструментов мониторинга или логирования для приложения. Например, Vercel OpenTelemetry:
import { registerOTel } from '@vercel/otel'
export function register() {
registerOTel('next-app')
}
Так как данный файл вызывается во всех средах исполнения, можно указать, какие файлы в какой среде будут исполнены:
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./instrumentation-node')
}
if (process.env.NEXT_RUNTIME === 'edge') {
await import('./instrumentation-edge')
}
}
Новые навигационные хуки onNavigate и useLinkStatus
Их цель - увеличить возможности контроля за роутингом и побочными эффектами на стороне клиента.
onNavigate - новый пропс для компонента <Link>
из next/link
, очень похож на onClick
, но не срабатывает на:
- на
Ctrl/Cmd + Click
- внешние
URLs
- ссылки с атрибутом
download
Можно отменять навигацию при помощи e.preventDefault()
Рекомендуется использовать для событий, которые должны происходить на стороне реальной сессии клиента: анимации, защита навигации, аналитика.
Как пример: блокирование перехода на другую страницу, если пользователь не сохранил данные, введенные в форме:
'use client' import Link from 'next/link'
import { useNavigationBlocker } from '../contexts/navigation-blocker'
interface CustomLinkProps extends React.ComponentProps<typeof Link> { children: React.ReactNode }
export function CustomLink({ children, ...props }: CustomLinkProps) {
const { isBlocked } = useNavigationBlocker()
return (
<Link onNavigate={(e) => {
if (
isBlocked &&
!window.confirm('You have unsaved changes. Leave anyway?')
) {
e.preventDefault()
}
}}
{...props}>
{children}
</Link> ) }
useLinkStatus
Хук, возвращающий { pending }
для локальных индикаторов загрузки при переходах между страницами.
Сделан по образцу useFormStatus
из React. Есть несколько условий для правильной работы хука:
- компонент с
useLinkStatus
должен располагаться внутри компонента<Link>
prefetching
отключен или уже выполняется, что означает блокировку навигации- роут назначения динамический и не содержит
loading.js
, из-за которого навигация была бы моментальной - не поддерживается в pages router
Пример с кастомной ссылкой:
import Link, { LinkProps } from "next/link";
import LoadingIndicator from "./loading-indicator";
const CustomLinkWithLoader = (props: LinkProps & { children: React.ReactNode }) => {
return <Link {...props}>
{props.children}
<LoadingIndicator />
</Link>
}
export default CustomLinkWithLoader;
'use client' import { useLinkStatus } from 'next/link'
export default function LoadingIndicator() {
const { pending } = useLinkStatus()
return pending ? (
<div role="status" aria-label="Loading" className='loader' /> )
: null
}
Я уже добавил нововведение с useLinkStatus
в свой проект, вместо лоадера рядом с сылкой я добавляю тонкий прогресс-бар сверху страницы - UX заметно лучше.
Есть и другие мелкие изменения, с ними можно ознакомиться на официальной странице обновления Nextjs 15.3, перейдя по ссылкам в ПРы с изменениями.
Итог
Обновление получилось полезным и некоторые фичи уже начал использовать на своих проектах, особенно порадовали Turbopack
для продакшн и хук useLinkStatus
.