BackНазад к блогу

Next.js 10

Next.js 10 представляет встроенную оптимизацию изображений, интернационализированную маршрутизацию, аналитику Next.js, поддержку React 17 и многое другое!

Мы рады представить Next.js 10 с новыми возможностями:

Встроенный компонент изображения и автоматическая оптимизация изображений

Наша цель с Next.js — улучшить две вещи: Опыт разработчика (DX) и Пользовательский опыт (UX).

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

Мы представили более 20 новых функций, улучшающих производительность и опыт разработки. При этом размер JavaScript-кода ядра Next.js уменьшился на 16%.

В январе мы представили новую передовую стратегию разделения кода JavaScript в сотрудничестве с командой Google Chrome.

Например, Barnebys увидели сокращение размера приложения на 23%, а Sumup — уменьшение их самого большого JavaScript-бандла на 70%. Эти улучшения были достигнуты без изменения кода в их приложениях Next.js.

Компании автоматически получили преимущества этой новой стратегии, просто обновив Next.js до последней версии.

Изображения в вебе

Хотя наша фокусировка на уменьшении объема JavaScript дала результаты, веб — это не только JavaScript: это также разметка и изображения.

Изображения занимают 50% от общего объема данных на веб-страницах.

Изображения сильно влияют на Largest Contentful Paint (LCP), так как они часто являются самым большим видимым элементом при загрузке страницы. LCP — это ключевой показатель веб-виталов, который Google скоро начнет учитывать в поисковом ранжировании.

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

Сегодня пользователи просматривают веб с телефонов, планшетов и ноутбуков, но изображения по-прежнему загружаются в одном размере. Например: сайты загружают изображение 2000×2000 пикселей, хотя телефоны отображают его как 100×100 пикселей.

Более того, 30% изображений на веб-страницах находятся за пределами начального вьюпорта, то есть браузер загружает изображения, которые пользователь не видит, пока не прокрутит страницу.

У изображений часто отсутствуют свойства width и height, из-за чего они "прыгают" при загрузке страницы. Это ухудшает показатель Cumulative Layout Shift (CLS).

99.7% изображений на сайтах не используют современные форматы вроде WebP.

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

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

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

Компонент изображения Next.js

Мы рады представить наше решение для производительных изображений в вебе: компонент изображения Next.js и автоматическую оптимизацию изображений.

В своей базовой форме компонент изображения Next.js — это замена HTML-элемента <img>, адаптированная для современного веба.

<img
  src="/profile-picture.jpg"
  width="400"
  height="400"
  alt="Profile Picture"
/>
import Image from 'next/image';
<Image
  src="/profile-picture.jpg"
  width="400"
  height="400"
  alt="Profile Picture"
/>;

Команда Google Chrome помогла создать этот React-компонент, чтобы улучшить производительность страниц, сделав лучшие практики стандартными.

При использовании компонента next/image изображения автоматически лениво загружаются, то есть рендерятся только когда пользователь приближается к их просмотру. Это предотвращает загрузку тех 30% изображений вне начального вьюпорта.

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

Хотя width и height у HTML-элемента <img> могут вызывать проблемы с адаптивными макетами, это не относится к next/image. При использовании next/image изображение автоматически становится адаптивным на основе соотношения сторон из указанных width и height.

Разработчики могут отмечать изображения в начальном вьюпорте, позволяя Next.js автоматически предзагружать их. Предзагрузка таких изображений показала улучшение Largest Contentful Paint до 50%.

Автоматическая оптимизация изображений

Даже с этими улучшениями по сравнению с HTML-элементом <img> остается серьезная проблема. Изображение 2000×2000 пикселей отправляется на телефоны, которые отображают его в меньшем размере.

В Next.js 10 мы решаем и эту проблему. Компонент next/image будет автоматически генерировать уменьшенные размеры через встроенную оптимизацию изображений.

Встроенная оптимизация автоматически отдает изображения в современных форматах вроде WebP (примерно на 30% меньше JPEG), если браузер их поддерживает. Это также позволяет Next.js автоматически адаптировать будущие форматы изображений и отдавать их поддерживающим браузерам.

Оптимизация работает с любым источником изображений. Даже если изображения приходят из внешнего источника (например, CMS), они оптимизируются.

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

Заключение

Новый компонент next/image и автоматическая оптимизация изображений — мощные примитивы, которые значительно улучшат пользовательский опыт.

Компонент next/image обеспечивает автоматическую ленивую загрузку, предзагрузку ключевых изображений, правильные размеры на всех устройствах и поддержку современных форматов. Эти функции работают с изображениями из любого источника.

Мы с нетерпением ждем, насколько быстрее станет ваш пользовательский опыт с этими новыми возможностями.

Подробнее читайте в документации по компоненту изображения и автоматической оптимизации.

Интернационализированная маршрутизация

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

Например, мы узнали, что 72% потребителей с большей вероятностью останутся на вашем сайте, если он переведен, а 55% заявили, что покупают только на сайтах электронной коммерции на родном языке.

Если вы планируете выходить на рынок другой страны, интернационализация вашего проекта критически важна для успеха.

Интернационализация проекта имеет два основных аспекта: Переводы и Маршрутизация.

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

Поэтому в Next.js 10 мы представляем встроенную поддержку интернационализированной маршрутизации и определения языка.

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

Next.js 10 поддерживает две самые распространенные стратегии маршрутизации: подпути и домены.

Для обеих стратегий вы начинаете с настройки локалей в конфигурации Next.js.

next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'nl'],
    defaultLocale: 'en',
  },
};

Локали соответствуют UTS Locale Identifiers — стандартизированному формату определения локалей.

Обычно идентификатор локали состоит из языка, региона и письменности, разделенных дефисом: язык-регион-письменность. Регион и письменность не обязательны. Примеры:

  • en-US — английский (США)
  • nl-NL — нидерландский (Нидерланды)
  • nl — нидерландский без указания региона

После настройки локалей вы можете выбрать стратегию подпутей или доменов.

Маршрутизация по подпутям

Маршрутизация по подпутям помещает локаль в URL. Это позволяет всем языкам находиться на одном домене.

Например, вы можете вставить локаль в URL как /nl-nl/blog и /en/blog.

Маршрутизация по доменам

Маршрутизация по доменам позволяет сопоставить локаль с доменом верхнего уровня. Например, example.nl может быть сопоставлен с локалью nl, а example.com — с локалью en.

Для маршрутизации по доменам требуется дополнительная конфигурация:

next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'nl'],
    domains: [
      {
        domain: 'example.com',
        defaultLocale: 'en',
      },
      {
        domain: 'example.nl',
        defaultLocale: 'nl',
      },
    ],
  },
};

Определение языка

Next.js 10 имеет встроенное определение языка для маршрута / на основе заголовка Accept-Language, который поддерживают все современные браузеры. Настроенные локали будут сопоставлены с заголовком Accept-Language, после чего произойдет перенаправление согласно выбранной стратегии.

Поисковая оптимизация

Поскольку Next.js знает язык посещаемой страницы, он автоматически добавляет атрибут lang к тегу <html>.

Next.js не знает о вариантах страницы, поэтому вам нужно самостоятельно добавлять метатеги hreflang через next/head. Подробнее о hreflang читайте в документации Google для вебмастеров.

Будущее интернационализации в Next.js

Интернационализированная маршрутизация — первая в серии функций, которые упростят интернационализацию и локализацию ваших проектов. Она позволяет интегрироваться с большинством React-библиотек для интернационализации.

Подробнее читайте в документации по интернационализированной маршрутизации.

Аналитика производительности Next.js

В Vercel мы знаем: нельзя улучшить то, что нельзя измерить.

Ваши посетители стали крайне чувствительны к производительности сайта. Более 50% из них покинут ваш сайт, если он загружается дольше 3 секунд. В электронной коммерции улучшение времени загрузки на 0.1 секунды приводило к росту конверсии на 1%.

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

С Next.js Speed Insights:

Вместо разовых измерений вы получаете непрерывный мониторинг.

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

Next.js Speed Insights дает полную картину, глубокое понимание вашей аудитории и того, как ваше приложение работает для пользователей.

Мы настаиваем на сборе реальных данных, потому что причины низкой производительности не всегда очевидны. Регрессии могут возникать из-за множества факторов — сторонних скриптов и стилей, или собственных шрифтов, изображений и видео, которые слишком велики или медленны.

Core Web Vitals

Google совместно с Web Performance Working Group разработали набор метрик для точного измерения воспринимаемой пользователями производительности вашего сайта: так называемые Core Web Vitals (Ключевые веб-метрики). Это показатели, которые отслеживают воспринимаемую скорость загрузки, отзывчивость и визуальную стабильность вашего сайта — все три критически важны для его общего состояния!

Воспринимаемую скорость загрузки можно измерить с помощью Largest Contentful Paint (LCP) — момента, когда отобразится основной контент страницы. Например, когда я открываю ссылку для покупки кроссовок — время до появления изображения кроссовок, их цены и кнопки "Добавить в корзину" и есть LCP.

Отзывчивость страницы измеряется First Input Delay (FID) — задержкой перед реакцией на первое взаимодействие пользователя. Например, время между моим кликом на "Добавить в корзину" и обновлением количества товаров в корзине — это FID.

Наконец, визуальная стабильность измеряется Cumulative Layout Shift (CLS) — тем, насколько смещаются элементы после отображения. Например, мы все сталкивались с ситуацией, когда кнопка "уплывает" из-за поздней загрузки изображения — это и есть layout shift.

Непрерывное измерение этих метрик для реальных пользователей крайне важно. Только так можно точно понять, как ваш сайт работает для них. Производительность может сильно варьироваться в зависимости от устройства пользователя, условий сети или характера взаимодействия. Сайты с персонализированным контентом или рекламой могут демонстрировать совершенно разную производительность для разных пользователей.

Эмуляционные тесты не могут уловить эти важные сигналы.

Next.js Speed Insights позволяет получать данные из реального мира, а не синтетические бенчмарки. Он обеспечивает непрерывный поток измерений вместо эпизодического тестирования, становясь частью рабочего процесса разработки.

Next.js Speed Insights позволяет получать данные из реального мира, а не синтетические бенчмарки. Он обеспечивает непрерывный поток измерений вместо эпизодического тестирования, интегрируясь в рабочий процесс разработки.

Посетите nextjs.org/analytics, чтобы узнать, как подключить его в своём приложении прямо сейчас.

Next.js Commerce

Электронная коммерция — одно из ключевых направлений использования веба. Новые возможности Next.js 10 предоставляют мощные инструменты для e-commerce.

Поэтому сегодня в сотрудничестве с BigCommerce мы выпускаем Next.js Commerce — универсальный стартовый набор на React для интернет-магазинов. Всего за несколько кликов разработчики Next.js могут клонировать, развернуть и полностью настроить его. Начните прямо сейчас на nextjs.org/commerce.

Поддержка React 17

React 17 не содержит критических изменений для Next.js, но потребовал некоторых обновлений, например, зависимостей. Новый JSX-трансформ автоматически активируется при использовании React 17, никаких изменений конфигурации не требуется.

Чтобы начать использовать React 17, просто обновите Next.js и React:

Terminal
npm install next@latest react@latest react-dom@latest

Быстрое обновление для getStaticProps / getServerSideProps

Теперь при редактировании функций getStaticProps и getServerSideProps Next.js автоматически перезапускает их и применяет новые данные. Это ускоряет итерации без необходимости обновлять страницу.

Подробнее о getStaticProps и getServerSideProps читайте в документации по получению данных.

Быстрое обновление для MDX

При использовании Next.js с MDX через @next/mdx изменения в MDX-контенте теперь используют быстрое обновление (Fast Refresh), избавляя от необходимости перезагружать страницу.

Документация @next/mdx объясняет, как настроить MDX в Next.js.

Импорт CSS из сторонних React-компонентов

Теперь можно импортировать CSS сторонних библиотек прямо в React-компоненты. Это позволяет разделять код CSS, предназначенный только для конкретного компонента. Например, можно использовать библиотеку react-datepicker без импорта CSS в _app.js:

components/MyComponent.js
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
 
function MyComponent() {}

Подробнее о встроенной поддержке CSS в Next.js читайте в документации.

Автоматическое разрешение href

При работе с динамическими маршрутами часто приходилось указывать как href, так и as для next/link:

<Link href="/categories/[slug]" as="/categories/books" />

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

Мы решили устранить эту проблему, упростив опыт разработчиков и пользователей. Теперь в Next.js 10 в большинстве случаев свойство as больше не требуется.

Это изменение полностью обратно совместимо — если вы используете и href, и as, поведение сохраняется.

Чтобы перейти на автоматическое разрешение href, просто укажите в href значение, которое раньше было в as:

<Link href="/categories/books" />

Подробнее о next/link и клиентской маршрутизации читайте в документации.

CLI @next/codemod

Мы стремимся к плавным обновлениям Next.js благодаря обратной совместимости. Когда функция устаревает и требует масштабных изменений, мы создаём codemod — автоматизированное преобразование кода.

Например, мы выпустили codemod для преобразования стрелочных и анонимных функций в именованные. Это необходимо, чтобы React Fast Refresh корректно распознавал компоненты.

В Next.js 10 мы представляем новый CLI-инструмент для codemod: npx @next/codemod <transform> <path>.

Подробнее о codemod читайте в документации.

Блокирующий fallback для getStaticPaths

В Next.js 9.3 мы представили getStaticProps и getStaticPaths с возможностью возвращать fallback для постепенной генерации статических страниц. По запросу пользователей мы добавили новый режим fallback: 'blocking', при котором первичный рендеринг происходит на сервере, а последующие запросы используют готовую страницу.

pages/posts/[id].js
export function getStaticPaths() {
  return {
    // активирует блокирующий режим для fallback
    fallback: 'blocking',
  };
}

Подробнее о fallback читайте в документации.

Поддержка redirect и notFound в getStaticProps / getServerSideProps

Теперь getStaticProps и getServerSideProps поддерживают возврат notFound и redirect.

Поддержка notFound

При возврате notFound: true отображается стандартная 404 страница с соответствующим статусом:

pages/posts/[id].js
export function getStaticProps() {
  return {
    // возвращает 404 страницу
    notFound: true,
  };
}

Поддержка redirect

Редиректы теперь можно возвращать напрямую, указывая destination и permanent (или statusCode):

pages/posts/[id].js
export function getStaticProps() {
  return {
    // редирект на внутреннюю страницу
    redirect: {
      destination: '/another-page',
      permanent: false,
    },
  };
}
pages/posts/[id].js
export function getServerSideProps() {
  return {
    // редирект на внешний домен
    redirect: {
      destination: 'https://example.com',
      permanent: false,
    },
  };
}

Заключение

Мы рады росту популярности Next.js:

  • Более 1300 независимых контрибьюторов, включая 120 новых после релиза 9.5
  • На GitHub проект получил более 54 800 звёзд.

Присоединяйтесь к сообществу Next.js в GitHub Discussions — здесь можно задавать вопросы и делиться своими работами.

Благодарности

Мы благодарим сообщество за вклад в этот релиз.

Спасибо контрибьюторам: @ijjk, @adebiyial, @elliottsj, @saintmalik, @HaNdTriX, @prateekbh, @amirsaeed671, @paambaati, @imagentleman, @gregrickaby, @Janpot, @atcastle, @Kirkhammetz, @remorses, @davidsonsns, @kmkzt, @slawekkolodziej, @Timer, @styfle, @timneutkens, @ykzts, @ashconnell, @orYoffe, @lfades, @justinwhall, @fbaiodias, @ludofischer, @felipeguilhermefs, @gr-qft, @TasukuUno, @YichiZ, @weichienhung, @seosmmbusiness, @HsuTing, @gsimone, @peduarte, @ztanner, @neighborhood999, @chibicode, @merceyz, @opudalo, @lunchboxav, @mohsen1, @akd-io, @justman00, @helloworld, @devknoll, @borekb, @ArthurMaverick, @sakito21, @TrySound, @omBratteng, @svenheden, @hallaji, @kettanaito, @vvo, @m-lautenbach, @jensmeindertsma, @Zeko369, @longlho, @stefanprobst, @laugharn, @sdornan, @daneroo, @mohd-akram, @austingmhuang, @sphilee, @devinekadeni, @Bacher, @nghiepit, @tomasdisk, @leader22, @paulogdm, @284km, @belgattitude, @geritol, @stigkj, @sampoder, @samrobbins85, @Pitasi, @digitalPlayer1125, @timfee, @plug-n-play, @philihp, @leerob, @dylanjha, @Kerumen, @rdimaio, @jorisw, @zerbinidamata, @jamesgeorge007, @Jashnm, и @futantan!