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

Next.js 7

После 26 канареечных релизов и 3.4 миллиона загрузок мы с гордостью представляем готовую к продакшену версию Next.js 7

После 26 канареечных релизов и 3.4 миллиона загрузок мы с гордостью представляем готовую к продакшену версию Next.js 7, включающую:

Наконец, мы рады поделиться этими новостями на полностью обновленном Nextjs.org

Улучшения DX

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

Скорость компиляции

Благодаря webpack 4, Babel 7 и множеству улучшений и оптимизаций в нашем коде, Next.js теперь запускается на 57% быстрее в процессе разработки.

Благодаря нашему новому инкрементальному кэшу компиляции, изменения в коде теперь собираются на 40% быстрее.

Вот некоторые примерные цифры, которые мы собрали:

6.07.0разница
Время запуска (базовое приложение)1947мс835мс57% быстрее
Изменение кода (базовое приложение)304мс178мс42% быстрее

В качестве бонуса, при разработке и сборке вы теперь будете видеть лучшую обратную связь в реальном времени благодаря webpackbar:

Лучшее сообщение об ошибках с React Error Overlay

Точное и полезное отображение ошибок критически важно для отличного опыта разработки и отладки. До сих пор мы отображали сообщение об ошибке и её стек вызовов. Теперь мы используем react-error-overlay, чтобы обогатить стек вызовов:

  • Точное расположение ошибок как на сервере, так и на клиенте
  • Подсветка исходного кода для контекста
  • Полный детализированный стек вызовов

Вот сравнение наших сообщений об ошибках до и после:

Предыдущее оверлей слева, react-error-overlay справа

Предыдущее оверлей слева, react-error-overlay справа

В качестве бонуса, react-error-overlay позволяет легко открыть ваш текстовый редактор, просто кликнув на определенный блок кода.

Webpack 4

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

Среди них:

  • Поддержка .mjs исходных файлов
  • Улучшения разделения кода
  • Лучшая поддержка tree-shaking (удаление неиспользуемого кода)

Еще одна новая функция — поддержка WebAssembly, Next.js даже может рендерить WebAssembly на сервере, вот пример.

Примечание: это обновление полностью обратно совместимо. Однако, если вы используете пользовательские загрузчики или плагины webpack через next.config.js, вам может потребоваться их обновить.

Импорты CSS

С webpack 4 был представлен новый способ извлечения CSS из бандлов, называемый mini-extract-css-plugin.

@zeit/next-css, @zeit/next-less, @zeit/next-sass и @zeit/next-stylus теперь работают на mini-extract-css-plugin.

Новая версия этих плагинов Next.js решает 20 существующих проблем, связанных с импортом CSS; Например, теперь поддерживается импорт CSS в динамических import():

components/my-dynamic-component.js
import './my-dynamic-component.css';
 
export default function MyDynamicComponent() {
  return <h1>Мой динамический компонент</h1>;
}
pages/index.js
import dynamic from 'next/dynamic'
 
const MyDynamicComponent = dynamic(import('../components/my-dynamic-component'))
 
export default function Index() {
  return () {
    <div>
      <MyDynamicComponent/>
    </div>
  }
}

Важное улучшение — теперь вам больше не нужно добавлять следующее в pages/_document.js:

<link rel="stylesheet" href="/_next/static/style.css" />

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

Короче говоря, все, что вам нужно сделать для поддержки импорта .css файлов в вашем проекте Next.js — просто зарегистрировать плагин withCSS в вашем next.config.js:

const withCSS = require('@zeit/next-css');
module.exports = withCSS({
  /* моя next конфигурация */
});

Стандартизированные динамические импорты

Next.js поддерживал динамические импорты через next/dynamic с версии 3.

Как ранние пользователи этой технологии, нам пришлось написать собственное решение для обработки import().

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

Из-за этого Next.js не поддерживал несколько функций import(), которые webpack представил позже.

Например, было невозможно вручную именовать и объединять определенные файлы вместе:

import(/* webpackChunkName: 'my-chunk' */ '../lib/my-library');

Другой пример — использование import() без обертки в модуль next/dynamic.

Начиная с Next.js 7 мы больше не изменяем стандартное поведение import(). Это означает, что вы получаете полную поддержку import() из коробки.

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

pages/index.js
import dynamic from 'next/dynamic';
 
const MyComponent = dynamic(import('../components/my-component'));
 
export default function Index() {
  return (
    <div>
      <MyComponent />
    </div>
  );
}

Этот пример создает новый JavaScript-файл для my-component и загружает его только при рендеринге <MyComponent />.

Важно отметить, что если компонент не рендерится, тег <script> не включается в начальный HTML-пейлоад.

Чтобы еще больше упростить наш код и использовать отличную экосистему React, в Next.js 7 next/dynamic был переписан для использования react-loadable под капотом (с небольшими изменениями). Это также вводит две новые отличные функции для динамических компонентов:

  • Таймауты с использованием опции timeout в next/dynamic
  • Задержка компонента загрузки с использованием опции delay в next/dynamic. Эта задержка позволяет вашему компоненту loading ждать x времени перед рендерингом состояния загрузки, например, если импорт очень быстрый.

Babel 7

Next.js 6 представил Babel 7, когда он еще находился в бета-версии. С тех пор была выпущена стабильная версия Babel 7, и Next.js 7 теперь использует эту версию.

Полный список изменений можно найти в релизных заметках Babel.

Некоторые из основных функций:

  • Поддержка Typescript, для Next.js вы можете использовать @zeit/next-typescript
  • Поддержка синтаксиса фрагментов <>
  • Поддержка babel.config.js
  • Свойство overrides для применения пресетов/плагинов только к подмножеству файлов или каталогов

Если у вас нет пользовательской конфигурации Babel в вашем проекте Next.js, нет никаких критических изменений.

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

Если вы обновляетесь с версии ниже Next.js 6, вы можете использовать отличный инструмент babel-upgrade.

В дополнение к обновлению до Babel 7, пресет Next.js для Babel (next/babel) теперь по умолчанию устанавливает опцию modules в commonjs, когда NODE_ENV установлен в test.

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

.babelrc
{
  "env": {
    "development": {
      "presets": ["next/babel"]
    },
    "production": {
      "presets": ["next/babel"]
    },
    "test": {
      "presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }]]
    }
  }
}

С Next.js 7 это становится:

.babelrc
{
  "presets": ["next/babel"]
}

На этом этапе .babelrc можно удалить, так как Next.js автоматически будет использовать next/babel, когда нет конфигурации Babel.

Меньший начальный HTML-пейлоад

Поскольку Next.js предварительно рендерит HTML, он оборачивает страницы в стандартную структуру с <html>, <head>, <body> и JavaScript-файлами, необходимыми для рендеринга страницы.

Этот начальный пейлоад ранее составлял около 1.62kB. В Next.js 7 мы оптимизировали начальный HTML-пейлоад, теперь он составляет 1.5kB, что на 7.4% меньше, делая ваши страницы более легкими.

6.07.0разница
Размер документа (рендер на сервере)1.62кб1.50кб7.4% меньше

Основные способы, которыми мы уменьшили размер:

  • Удален div __next-error
  • Встроенные скрипты минифицированы, в будущем релизе они будут полностью удалены
  • Удалены неиспользуемые свойства __NEXT_DATA__, когда они не используются, например, свойства nextExport и assetPrefix.

Поддержка статического CDN

В Next.js 5 мы представили поддержку assetPrefix, способ заставить Next.js автоматически загружать ассеты из определенного места, обычно CDN. Эта опция отлично работает, если ваш CDN поддерживает проксирование, вы запрашиваете URL, например:

https://cdn.example.com/_next/static/<buildid>/pages/index.js

Обычно CDN проверяет, есть ли файл в его кэше, или запрашивает его напрямую с источника.

Проксирование ассетов — именно так работает Edge Network.

Однако некоторые решения требуют предварительной загрузки каталога напрямую в CDN. Проблема в том, что структура URL Next.js не соответствовала структуре папок внутри каталога .next. Например, наш предыдущий пример:

https://cdn.example.com/_next/static/<buildid>/pages/index.js
// соответствовало:
.next/page/index.js

В Next.js 7 мы изменили структуру каталога .next, чтобы она соответствовала структуре URL:

https://cdn.example.com/_next/static/<buildid>/pages/index.js
// соответствовало:
.next/static/<buildid>/pages/index.js

Хотя мы рекомендуем использовать CDN с проксированием, эта новая структура позволяет пользователям другого типа CDN загружать каталог .next в их CDN.

Styled JSX v3

Мы рады представить styled-jsx 3, решение CSS-in-JS, включенное в Next.js по умолчанию, теперь готово для React Suspense.

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

pages/index.js
const ChildComponent = () => (
  <div>
    <p>некоторый текст</p>
  </div>
);
 
export default function Index() {
  return (
    <div>
      <ChildComponent />
      <style jsx>{`
        p {
          color: black;
        }
      `}</style>
    </div>
  );
}

Приведенный выше код пытается выбрать тег p, но не работает, потому что стили styled-jsx ограничены текущим компонентом, они не просачиваются в дочерние компоненты. Один из способов обойти это — использовать метод :global, удаляя префикс из тега p. Однако это вводит новую проблему — стили просачиваются по всей странице.

В styled-jsx 3 эта проблема решена введением нового API, css.resolve, который будет генерировать className и теги <style> (свойство styles) для данной строки styled-jsx:

pages/index.js
import css from 'styled-jsx/css';
 
const ChildComponent = ({ className }) => (
  <div>
    <p className={className}>некоторый текст</p>
  </div>
);
 
const { className, styles } = css.resolve`
  p {
    color: black;
  }
`;
 
export default function Index() {
  return (
    <div>
      <ChildComponent className={className} />
      {styles}
    </div>
  );
}

Этот новый API позволяет прозрачно передавать пользовательские стили в дочерние компоненты.

Поскольку это мажорный релиз для styled-jsx, есть одно критическое изменение, которое улучшает размер бандла, если вы используете styles-jsx/css. В styled-jsx 2 мы генерировали "ограниченную" и "глобальную" версии внешних стилей, даже когда использовалась только "ограниченная" версия, мы все равно включали "глобальную" версию этих внешних стилей.

В styled-jsx 3 глобальные стили должны быть помечены css.global вместо css, чтобы styled-jsx мог оптимизировать размер бандла.

Полный список изменений можно найти в релизных заметках.

React Context с SSR между App и Pages

Начиная с Next.js 7 мы теперь поддерживаем новый API React context между pages/_app.js и компонентами страниц.

Ранее было невозможно использовать React context между страницами на стороне сервера. Причина в том, что webpack сохраняет внутренний кэш модулей вместо использования require.cache, мы написали пользовательский плагин webpack, который изменяет это поведение для совместного использования экземпляров модулей между страницами.

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

6.07.0разница
Использование памяти57.5МБ48.1МБ-16% памяти

nextjs.org

Вместе с релизом Next.js 7 мы запускаем полностью переработанный nextjs.org.

Блог

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

Новый nextjs.org

Новый nextjs.org

Вдохновляйтесь

Количество приложений, использующих Next.js, постоянно растёт, и нам нужен был способ показать все эти прекрасные приложения в одном обзоре. Знакомьтесь с новой страницей /showcase:

Вдохновляйтесь на nextjs.org/showcase

Вдохновляйтесь на nextjs.org/showcase

Этот новый раздел позволяет нам постоянно добавлять новые приложения, созданные с помощью Next.js.

Приглашаем вас посетить /showcase для вдохновения или отправить своё приложение, использующее Next.js!

Сообщество

С момента первого релиза Next.js используется во всём — от компаний из списка Fortune 500 до личных блогов. Мы очень рады видеть рост популярности Next.js.

  • В настоящее время более 12 500 публично индексируемых доменов используют Next.js.
  • Более 500 участников внесли хотя бы один коммит.
  • На GitHub проект получил более 29 000 звёзд.
  • С момента первого релиза было создано почти 2200 пул-реквестов.

Сообщество Next.js насчитывает почти 2000 участников. Присоединяйтесь!