Мы рады представить Next.js 5.0. Эта версия уже доступна в npm. Для обновления выполните:
npm i next@latest react@latest react-dom@latest
Помимо обновления Next.js, мы также обновили peer-зависимости
react
иreact-dom
Next.js — это инструментарий для универсальных React-приложений с серверным рендерингом (или статической предварительной генерацией). Начать разработку приложения любого масштаба так же просто, как выполнить next
. (Подробнее.)
С каждым новым релизом мы стремимся сохранять обратную совместимость, предлагать простые пути обновления и вносить изменения в API только при крайней необходимости. Next.js 5.0 не исключение.
Однако внутри Next.js претерпел радикальные изменения, чтобы обеспечить новые мощные сценарии использования и расширяемость. Мы начали с того, что сделали Next.js использующим универсальный конвейер Webpack как для серверного, так и для клиентского кода.
Универсальный Webpack и плагины Next
Next.js использует мощные инструменты, такие как Webpack, Babel и Uglify, предоставляя конечному пользователю простой интерфейс: next
(для разработки), next build
(для подготовки к продакшену) и next start
(для запуска сервера) или next export
для предварительного рендеринга в статические файлы.
Одно из ранних решений, которое мы приняли — предоставить мощные точки расширения для настройки этих инструментов. Мы хотели не только простоту использования, но и гибкость для расширения инструментария по вашему усмотрению.
Например, вы можете расширить конфигурацию Webpack в Next.js, настроив свойство webpack
в вашем next.config.js
.
Поскольку Webpack работает по-разному в продакшене и разработке, мы решили сделать его функцией, которая декорирует нашу конфигурацию Webpack по умолчанию:
module.exports = {
webpack(config, { dev }) {
// модифицируем!
return config;
},
};
Пример необязательного файла
next.config.js
Однако Webpack работал только с клиентскими (браузерными) бандлами, и вы упускали возможность использовать этот мощный инструментарий для серверного рендеринга.
Мы рады объявить, что полностью переработали наш код, чтобы сделать Webpack универсальным.
С вашей стороны все изменения сводятся к тому, что в декоратор передается дополнительное свойство isServer
. Однако новая семантика означает, что теперь вы можете использовать всю экосистему загрузчиков Webpack.
CSS, LESS, SASS, SCSS и CSS Modules
Одна из самых востребованных функций — возможность импорта CSS-файлов и использования загрузчиков Webpack:
import './index.css';
export default function Index() {
return (
<div>
<p>I love CSS!</p>
</div>
);
}
Пример страницы (
pages/index.js
), использующей импорт CSS благодаря универсальному Webpack
Чтобы это работало, вы можете добавить необходимые загрузчики как peer-зависимости:
npm i --save css-loader style-loader postcss-loader
Next.js дает вам свободу выбора нужных загрузчиков и их обновления до разных версий по вашему усмотрению.
Затем расширьте конфигурацию для настройки загрузчиков. В next.config.js
:
module.exports = {
webpack(config, options) {
const { dev, isServer } = options;
const extractCSSPlugin = new ExtractTextPlugin({
filename: 'static/style.css',
disable: dev,
});
config.module.rules.push({
test: /\\.css$/,
use: cssLoaderConfig(extractCSSPlugin, {
cssModules,
dev,
isServer,
}),
});
return config;
},
};
Расширение конфигурации Webpack дает вам большую гибкость и контроль
Хотя мы рекомендуем использовать решения для локальных стилей компонентов, такие как встроенный плагин Babel styled-jsx
, мы считаем, что CSS-загрузчики имеют важные преимущества, например, упрощают повторное использование существующих CSS-кодовых баз и значительно облегчают миграцию старых кодовых баз в Next.js.
Вместо включения всех возможных функций и загрузчиков по умолчанию мы представляем плагины Next.js — простые функции, которые декорируют вашу конфигурацию. Вместо ручного расширения конфигурации, как мы сделали выше, вы можете просто:
const withCss = require('next-css');
module.exports = withCss({
/* дополнительная необязательная конфигурация */
});
Все, что нужно для включения импорта
.css
файлов — подключитьnext-css
Подробнее об использовании CSS-загрузчиков с Next.JS или обратитесь к некоторым уже созданным нами пакетам:
Наша цель — дать сообществу возможность развивать и расширять экосистему практичных и простых расширений. Для этого мы открываем монорепозиторий next-plugins для поддержки сообществом Next.js. Все PR приветствуются!
Поддержка TypeScript
Одна из самых быстрорастущих технологий в экосистеме JavaScript — TypeScript. Настолько, что она получает официальную поддержку в Babel 7, что означает ее естественную поддержку в Next.js через настройку вашего .babelrc.
Тем временем, благодаря нашей новой поддержке универсального Webpack, вы уже можете получить полную поддержку TypeScript сегодня!
Вы можете расширить конфигурацию Webpack следующим образом:
module.exports = {
webpack(config, options) {
const { dir, defaultLoaders } = options;
config.resolve.extensions.push('.ts', '.tsx');
config.module.rules.push({
test: /\\.+(ts|tsx)$/,
include: [dir],
exclude: /node_modules/,
use: [
defaultLoaders.babel,
{ loader: 'ts-loader', options: { transpileOnly: true } },
],
});
return config;
},
};
Все, что нам нужно сделать — включить
ts-loader
Как и CSS-загрузчики и препроцессоры, TypeScript была одной из самых востребованных функций. Чтобы упростить ее включение в проекты, как и любой другой загрузчик, мы теперь предоставляем плагин next-typescript
, который можно включить в файл next.config.js
:
const withTs = require('next-typescript');
module.exports = withTs({
/* дополнительная конфигурация */
});
Плагины можно легко компоновать: они просто функции
Лучшая поддержка альтернативных реализаций React и переопределения модулей
Со временем появилось множество альтернативных реализаций React. Среди них стоит отметить [preact
](https://preactjs.com/), nervjs
и inferno
.
Другие библиотеки фокусируются на замене рендерера DOM, например react-dom-lite
, которая стремится сделать сборку React меньше, вводя небольшие компромиссы в совместимости с браузерами.
Поддержка универсального Webpack делает процесс включения этих библиотек в качестве замен еще проще. По аналогии с другими плагинами, вот все, что нужно для использования Next.js с preact:
npm i @zeit/next-preact preact preact-compat
Устанавливаем плагин preact и необходимые peer-зависимости
const withPreact = require('@zeit/next-preact');
module.exports = withPreact();
Наш новый
next.config.js
готов к работе с preact
Ознакомьтесь с очень простым модулем @zeit/next-preact или создайте свой собственный!
Опциональные внешние source maps в продакшене
Теперь, когда Next.js использует webpack как для клиентского, так и для серверного кода, включение source maps в продакшен-сборках требует лишь небольшой настройки конфигурации.
В режиме разработки source maps включаются автоматически, поэтому для продакшена мы настраиваем их иначе:
module.exports = {
webpack(config, { dev }) {
if (!dev) {
config.devtool = 'source-map';
}
return config;
},
};
Мы просто по-разному настраиваем опцию
devtool
вне режима разработки
Зоны (Zones)
Одной из заявленных целей Next.js с самого начала было возвращение и сохранение простоты веба.
Серверный рендеринг (SSR), простой и агностичный подход к получению данных и декларативные страницы на основе файловой структуры — вот некоторые из функций, которые мы внедрили в соответствии с этой философией.
Часто упускаемый из виду аспект веб-сервисов и сайтов — их естественная композируемость и масштабируемость.
Например, mydomain.com/settings
и mydomain.com/
могут быть двумя совершенно разными приложениями, развернутыми независимо, масштабируемыми отдельно и даже работающими на разных версиях одного и того же ПО.
Все, что нужно для "склеивания" их в единый опыт для конечного пользователя — это простая настройка бэкенд-роутинга или балансировщиков нагрузки, которые предоставляют их миру. Мы рады представить возможность компоновки нескольких приложений, построенных на Next.js, соединенных с помощью обычных компонентов <Link>
. Мы называем эту функцию Зонами (Zones).
В качестве примера рассмотрим два независимых приложения Next.js, развернутых на Vercel:
- https://front.vercel.app
- https://zeit-docs-zbqbsrucga.vercel.app/docs https://zeit-docs-zbqbsrucga.vercel.app/api
Обе страницы выглядят единообразно, но принадлежат разным приложениям
Когда мы перерабатывали нашу документацию, мы хотели максимально упростить процесс внесения изменений сообществом.
Мы решили выделить "мини-сайт" документации в отдельный репозиторий. Кроме того, при каждом пул-реквесте и предложении изменений мы автоматически развертываем его изолированно:
При каждом изменении в PR наш бот автоматически развертывает его
В итоге у нас получилось две зоны, объединенные в родительский домен https://vercel.com
с помощью нашей функции алиасов путей. Это выглядит примерно так:
{
"rules": [
{ "pathname": "/docs", "dest": "our-docs.vercel.app" },
{ "pathname": "/api", "dest": "our-docs.vercel.app" },
{ "dest": "my-main-website.vercel.app" }
]
}
Эти простые правила позволяют комбинировать микросервисы и зоны
Остается только выполнить команду now alias
:
now alias -r rules.json my-domain.com
Наша миссия — сделать развертывание максимально универсальным и открытым. Для помощи в локальной разработке мы недавно открыли исходный код micro-proxy
— инструмента, работающего с тем же форматом конфигурации, что показан выше.
Аналогично вы можете объединять зоны с другими решениями, такими как Nginx, HAProxy или API Gateway.
Ускоренные продакшен-сборки
Мы считаем, что опыт разработчика и пользовательский опыт идут рука об руку. Чем эффективнее можно писать, тестировать и развертывать изменения, тем быстрее добавляются новые функции, исправляются ошибки и улучшается общий пользовательский опыт.
Следовательно, мы продолжаем сосредотачиваться на постоянном улучшении производительности базовых строительных блоков системы.
В Next.js 5.0 у нас была возможность снова взглянуть на команду next build
, которую вы запускаете перед развертыванием в продакшен или экспортом статического сайта из вашего приложения Next.js.
Мы рады сообщить, что для vercel.com — React-приложения, состоящего из тысяч компонентов, — мы наблюдали значительные улучшения с Next.js 5.0: ускорение продакшен-сборок на 23.6%:
Сборка нашего основного приложения теперь завершается на 38 секунд быстрее
Улучшенное кэширование для динамических импортов
При использовании динамического import()
WebPack получает сигнал о новом entry-point'е для разделения кода.
Во время сборки это означает создание отдельного бандла для соответствующего поддерева модулей.
До Next.js 5.0 динамические бандлы получали URL следующего вида:
/_next/1517592683901/webpack/chunks/components_hello1_1345d10fc951cd6717c5676c467579a6.js
Теперь мы преобразовали динамические импорты в хеши содержимого поддерева:
/_next/webpack/chunks/components_hello1_1345d10fc951cd6717c5676c467579a6-b7874680a9e21fb6eb89.js
Это означает, что при повторных развертываниях ваши пользователи не будут повторно загружать уже использованный код.
Фрагменты (Fragments)
Next.js создает компонент верхнего уровня <Document>
, который рендерится на сервере для каждой страницы. Переопределение этого компонента дает вам полный контроль над разметкой, открывая множество продвинутых сценариев использования.
Частью этой начальной разметки является список скриптов, которые Next.js должен выполнить на стороне клиента. Пользовательский _document
выглядит так:
import Document, { Head, Main, NextScript } from 'next/document';
export default class extends Document {
render() {
return (
<html>
<Head />
<body>
<Main />
<NextScript />
</body>
</html>
);
}
}
Document
позволяет настраивать весь серверный вывод страницы
До недавнего времени мы были вынуждены оборачивать скрипты в <div>
.
С Next.js 5.0 мы теперь используем поддержку Fragment
, что приводит к более легковесным страницам и полному контролю над стилями без лишней разметки.
Более точные ошибки
Node.js не поддерживает source maps, поэтому ошибки на стороне сервера сопровождаются стектрейсом, указывающим на скомпилированный код.
В Next 5 мы улучшили поддержку source maps на сервере. Теперь ошибки при серверном рендеринге указывают на правильную функцию и номер строки.
Ошибки теперь показывают правильную строку, файл и имя функции
Заключение
Универсальный Webpack укрепляет основы Next.js и делает его еще более перспективным. В целом, больше нет искусственного разделения на то, какие плагины или загрузчики применимы к Next.js, а какие нет.
В духе нулевой конфигурации мы рады представить Next Plugins — репозиторий сообщества с рецептами, автоматически расширяющими функциональность Next.js без необходимости настройки отдельных параметров.
Теперь мы поддерживаем весь спектр решений для CSS, языков, компилируемых в JS, таких как TypeScript, и альтернатив React, таких как Nerve, просто добавляя дополнительный модуль и явно указывая его в next.config.js
. Простота без неясностей.
Зоны позволяют соединять приложения Next.js, не находящиеся в одном репозитории или даже на одних серверах. Мы считаем это важной вехой в категории улучшений "масштабируемости команд".
Таким образом, Next.js становится отличным кандидатом для крупных приложений, поддерживаемых несколькими командами. Теперь они могут развертывать улучшения параллельно, уменьшая поверхность ошибок, увеличивая скорость итераций и даже пробуя разные технологии в дополнение к нашему ядру, такие как различные подходы к управлению состоянием или получению данных.
Мы хотим воспользоваться возможностью поблагодарить Дипа Варму и инженерную команду Trulia за ключевые идеи, код и тестирование, которые привели к разработке этой функции.
Как всегда, этот релиз не состоялся бы без многих open-source-контрибьюторов и нашего замечательного сообщества.