Nextjs — самый быстрорастущий фреймворк. После создания, в 2016 году, было выпущено уже 12 обновлений, каждое из которых называлось компанией “крупнейшим”. 25 октября Vercel (компания, владеющая Nextjs) представит новый, 13 релиз, который, конечно же, вновь станет “крупнейшим”. Тем не менее, в этой статье речь пойдёт не конкретно о нём, а о действительно новом для компании процессе.

В мае этого года Nextjs неожиданно выпустил в своём блоге RFC (request for comments). В нём речь идёт, в первую очередь, о новой абстракции — layouts, а также о множестве связанных изменений, нацеленных на ускорение, улучшение DX и стандартизацию путём создания новых конвенций. Это рабочее предложение однозначно заслуживает внимания в меру своей громоздкости для фреймворка и потому, что буквально описывает его будущий вид.

Основное

Запрос на комментарии (RFC) - это официальный документ, разработанный Технической рабочей группой по Интернету (IETF), в котором описываются спецификации для конкретной технологии. Когда RFC ратифицируется, он становится официальным документом о стандартах [источник].

Подобные запросы есть у многих библиотек, в т.ч. и у React (https://github.com/reactjs/rfcs/), однако редко под них пишутся полноценные пресс-релизы. Nextjs описал своё видение, выпустив статью в блоге пять месяцев назад и дополнив его в сентябре. Также была создана дискуссия в github, в которой разработчикам предлагалось описать свои пожелания и замечания.

Данный запрос называют крупнейшим обновлением Nextjs. И, вероятно, это действительно так. Предлагается изменить структуру приложения и ввести новые абстракции, но обо всём по порядку.

Структура

Все страницы предлагается хранить в папке “app”. Прежде они хранились по пути pages, в дальнейшем эта папка продолжит работать, однако с некоторыми ограничениями. Первое время Nextjs будет обрабатывать страницы из обоих каталогов, чтобы сохранить обратную совместимость и дать возможность постепенного переноса страниц. По поводу имени папки в дискуссии есть споры, в связи с тем, что данное имя уже могло использоваться в приложении. Вполне вероятно, что к релизу она будет переименована.

Другим изменением в именовании стало имя страниц и правило их расположения. Раньше было 2 варианта — внутри папки с index файлом (/about/index.js), и в качестве файла (/about.js). При этом, несмотря на вариант, страница всегда собиралась в качества файла (/about.html). В новом стандарте предлагается создавать под каждую страницу новую папка с файлом page.js (/about/page.js).

Layout

Nextjs использует ряд абстракций, которые подвязываются к приложению автоматически — это _app, _document и _middleware. Middleware был добавлен в 12 версии в качестве тестового api, а в последних минорных релизах был изменён и переименован в middleware (без нижнего подчёркивания в начале). _app и _document, используемые для разметки документа и шаблона для всех страниц предлагается удалить. Их роль возьмёт на себе новая абстракция, которой, в первую очередь и посвящено предложение — layout.

Отличием layout от _document является то, что в layout на данный не работают стили. Частично эту проблему решит другое RFC, посвящённое добавлению поддержки глобальных стилей.

Layout делят на корневые, хранящиеся на верхнем уровне каталога app и дополнительные, хранящиеся в подкаталогах. В корневом будет описываться основная разметка — html, head и body, то есть фактически заменит _document. Дополнительные будут описывать шаблоны внутри body для вложенных страниц.

Приятным отличием layout является то, что в них можно вызывать getStaticProps и getServerSideProps (получать данные на этапе сборки или рендера страницы на сервере) и передавать нужные данные каждой вложенной странице. Прежде можно было только вызывать getInitialProps в _app, хоть и не рекомендовалось.

Лоадеры

Рендер некоторых страниц, особенно в режиме серверного рендеринга и с получением данных может занимать длительное время. По умолчанию всё это время пользователь видит пустой белый экран. Это портит пользовательский опыт, а если занимает слишком много времени (дольше 3 секунд), то часто приводит к потере пользователя. Для того, чтобы пользовательский опыт становился приятнее в таких местах стоит использовать лоадеры и скелетоны, которые будут создавать видимость активности и доступности сайта.

В React для подобного все ленивые элементы можно обернуть в Suspense. В Nextjs предлагается создавать файл loading.js, которые будет содержать компонент загрузки. В конечном счёте это соберётся в тот-же Suspense, но при этом код страницы не засоряется множеством обёрток.

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

Страницы ошибок

На данный момент в Nextjs для ошибок в корне каталога страниц можно создать файлы 404.js, 502.js и _error.js. То есть в статичном варианте только по одному варианту ошибки для всего приложения. Это было проблемой в том числе и для мультиязычных сайтов, в которых эту страницу нужно было как-то локализовывать. Также были ограничены возможности делать разные страницы ошибок для разделов (например для блога с последними статьями и кнопкой вернуться на главную блога).

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

Группировка страниц

Нередко бывает, что для страниц на одном уровне используется два разных шаблона или страниц ошибок, например один набор для работы приложения, а другой для продуктовых страниц. Эта проблема в будущем будет решена благодаря группам страниц. Страницы объединяются в новый подкаталог, имя группы оборачивается в скобки “(product)”.

Если создать группы на верхнем уровне приложения, то в них можно делать разные корневые layout-ы.

Перехватывающие роуты

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

Имена таких роутов начинаются с “(..)”, количество таких скобок в начале файла означает насколько высоко нужно подняться до нужного роута. Например, чтобы перехватить фотографии (/photo/) при открытии их со страницы статей (/blog/post-name/), внутри каталога статьи нужно создать каталог с именем (..)(..)photo. В нём может описать модальное окно и при переходе со страницы статьи откроется именно оно. Если поделиться ссылкой или перезагрузить страницу, то фотография откроется как обычная страница.

Параллельные роуты

Подобные роуты могут быть использованы для страниц, состоящих из двух сложных и несвязанных между собой сегментов. Например, если страница состоит из блога в верхней половине и FAQ-а в нижней.

Для такой страницы нужно будет создать директорию с layout.js и сегментами, из которых она будет состоять. Для создания сегментов нужно создать подкаталог, имя которого будет начинаться с “@” (напр. @posts и @faq). Затем в layout в качестве пропсов будут доступны данные сегменты и их можно будет встроить в нужные части в разметке.

Внутри сегментов могут быть подстраницы и при переходе на них в layout-е будет заменяться сегмент, к которому она принадлежит. То есть, например можно создать страницу статьи (/blog/@posts/some-post) и при перехода не неё сегмент @posts будет замещён этой страницей, а сегмент @faq останется без изменений.

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

Функционал React.js

Команда Next.js всегда подготавливается к будущим релизам react.js заранее. Так, поддержка react v18 появилась ещё до официального релиза версии, а серверные компоненты начали тестироваться ещё до их чёткого видения. В новом предложении помимо функционала Next.js, также описываются и серверные компоненты, которые теперь полноценно войдут в процесс.

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

Выводы

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

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

Уже 25 октября, в 19:30 CET (20:30 МСК), команда Vercel проведёт конференцию, на которой представит новый релиз Next.js. На ней однозначно пойдёт речь о данном RFC, но станет ли это частью следующей, 13-ой версии, в качестве готового к использованию функционала остаётся под вопросом.