Ну так как это по умолчанию серверные компоненты (а страницы всегда стоит держать серверными, иначе нельзя будет настроить для них мета-заголовки), то можно сделать просто общий роут и в нём возвращать либо один компонент, либо другой (кодна коленке):
const ProductOrPostPage = async ({ params }) => {
if (await isProduct(params.slug)) {
return <ProductPage slug={params.slug} /> // и внутри получать продукт, также асинхронно
}
return <PostPage slug={params.slug} /> // и внутри получать статью, также асинхронно
}
Ну а когда сайт полностью статический - должно хватить generateStaticParams (но думаю раз раньше не хватило getStaticPaths - скорее всего и это не поможет)
-----
А как проверяли какой вариант возвращать в кастомном роутере?
Не, путь и параметры самое базовое API и просить оборачивать все страницы с контекст для такого - ужасный DX (да и не везде вообще есть такая возможность). Пакет использует внутреннее API next.js.
На сервере можно использовать headers реквеста
headers включает режим серверного рендеринга, поэтому мы от него отказались и не используем в компонентах.
который потом будет прыгать когда подтянется значение из хука и media query
А почему нельзя сразу обойтись стилями и всё? Зачем это делать логикой?
Если компонент завязан на клиента и стилями никак не решить - делаем его только клиентским:
По багам не вписалось в статью, поэтому оставлю это в комментариях.
В 11 версии было решено завести i18n решение от next.js в коммерческий проект. Пара недель работы и… Странный баг, что вариант /en/en/page-name отображался как /page-name и разные артефакты от этого.
Как так вышло? Next.js проверял путь на наличие региона в начале и удалял его. Но эта логика повторялась примерно в десятке мест. Его удалось исправить в ядре, но оказалось, что для дефолтной локали всё ещё хуже и это не единственный артефакт. Как итог - откат.
Это произошло при тысячах тестов. Увы, но часто баги возникают именно на грани связок подобных параметров (таких как basePath, assetsPrefix, i18n).
Предположу, что этот функционал стал слишком провальным, так как next.js в новой версии даже не упоминает его и предлагает это делать через динамический сегмент (часть пути, в качестве которой могут быть разные варианты, в данном случае, например /[lang]/page-name) и middleware (как по итогу и было сделано в проекте).
Я делал относительно нормальный пет проект на нём. И первое время как-то нравилось - буквально plug-n-play - бери и делай, но вот с инпутом, кнопками и прочим с большим количеством условий (когда для элемента в css было бы 40 строк, а здесь это 40 классов) - как-то прям оттолкнуло.
Next.js уже лет 5 как не только про SSR, сейчас в первую очередь это про SSG с инкрементальной пересборкой.
А про 5 секунд действительно приукрасил, да. Знаете за сколько загружается эта страница на медленном 3g (что всё ещё является обыденным в мире и Европе)? 20 секунд, из которых 15 до загрузки LCP.
Facebook, вероятно, это сделал, чтоб трафик сэкономить, т.к. экономия 2кб со страницы на миллионы (или миллиарды?) пользователей и переходов - весомая экономия на серверах.
Вряд ли там вообще упоминались улучшение метрик и SEO-оптимизация.
Про SSR речи и не идёт - да и там другие проблемы бы были важнее, вроде долгого ожидания начала загрузки документа, что при хорошем интернете обычно даже дольше, чем сама загрузка.
А сайты продумываются для всех - многие заходят на страницу лишь единожды. А первый вход важен для маркетинговых задач. Если пользователь первый раз грузил страницу 5 секунд, устал и ушёл, то уже неважно, что данные у него закешировались и дальше всё будет грузиться быстро. (Когда речь идёт об оптимизациях таких мелочей, обычно это не про веб-приложения, а про маркетинговые сайты)
Бывает и такое, конечно, но имелось ввиду html документ со вшитыми стилями (т.е. когда стили не в отдельных файлах, а в теге <style />, в самой странице)
Удобство ломается с диким грохотов об блоки чуть сложнее карточки с закруглениями.
Когда для инпута нужно писать 10 классов на стили, по 5 классов на каждое состояние (hover, visites, disabled, ..., error), 15 классов на адаптив и ещё на всякий случай снаружи принимаешь классы, а то мало ли чего, ещё 20 классов нужно будет передать...
При сжатии gzip/brotli экономия на большой html будет в байтах, максимум - в паре килобайт. Это не повлияет на оценку Lighthouse и на пользовательский опыт, если вы не гонитесь за тысячными долями процента перфоманса
Да, при весе в 100кб сжатыми уменьшит на 5кб (если стили вшиты, например, а может и до 10кб, а может и 1 с трудом накапает, зависит). Это не меняет кардинально метрики, но, например, освобождается 5мб под прочее, может спрайт добавить внутрь? Да и 5кб + доли секунды в упрощении компрессии-декомпрессии сыграют в 1-2 балла (мы всё-таки ориентируемся на мобильные устройства).
При чтении дерева элементов в инспекторе видим несемантичные j1 g83 классы, соответственно как найти место в коде, в котором нужно поправить стиль? "
А зачем их читать? В режиме разработки можно настраивать генерирование классов по другому (пакет это поддерживает из коробки). В продакшене ты залезаешь обычно просто конкретный элемент подправить, скорее ради интереса.
Частично проблема решится CSS maps, но тоже много лишних телодвижений.
С картами и сентри очень хороший пункт, Спасибо! Вдруг тут кто-то обходил подобное и может поделиться решением?
А для автотестов классы больно и ненадёжно, атрибут всё же несравним. Мне больше всего нравится подход, когда этот атрибут добавляется во время сборки только в одном окружении, не в проде. Но такое не всем годится. Для накликивания можно было бы тоже сжимать классы только в проде, а все эти махинации проводить на тестовых стендах...
Стоит ли оно того, если есть другие минусы? Пожалуй нет; Стоит ли это попробовать? Почему бы и да. 1 день на аб тесте или ручное сравнение на тестовом стенде даст ответы, есть ли достаточный эффект.
P.S. Как не плюсануть коммент выше за хороший развёрнутый коммент?
CSS in JS ужасен, да, поэтому речь только о CSS-модулях. Сам Next.js тоже перестал рекомендовать css-in-js решения и сейчас везде говорят только про css/scss/sass и css-модули (ну ещё бывает tailwind, но с кем не бывает).
А сайты бывают и сложнее приложений, современным компаниям для продвижения и анализа нужно куда больше, чем просто текст и красивая анимация.
Имелось ввиду форматы, когда классы добавляются не по полноценному БЭМ-у (в котором есть сам класс и его модификаторы), а просто общие классы, то есть когда может быть: <div class="card section box pt-20 mb-8" /> Это bootstrap и tailwind, например. Но если bootstrap устроен всё-же по БЭМ-у, то tailwind просто огромный набор атомарок, который у меня язык не поворачивается назвать БЭМ-ом (и выглядит это порою очень страшно). Кто-нибудь, объясните мне, как это вообще выжило...
И до, и после (но в меньшем соотношении, да). Видел примеры, где эффект в сжатом виде стремительно приближался к нулю.
В самом худшем случае это небольшая разгрузка сервера и клиента, так как алгоритмам нужно проходить меньше символов. В лучшем - оптимизация. Вероятно будут страницы, где эффект хороший, а будут, где достаточно незаметный.
Если есть безобидный способ, пусть даже незначительно, сократить вес страницы, то почему бы и да.
Провожу много времени в попытках оптимизации сайтов. Пробовал svelte, шаблонизаторы, статику, и... они не дали явных преимуществ (особенно по сравнению с next.js v14 и серверными компонентами).
Всё это - виртуальный дом, множество логики, доп. библиотеки, в контексте next.js не влияют на FCP и LCP, так как Next в первую очередь выдаёт статику, и уже потом на клиенте, грубо говоря, виртуальный дом свяжется с настоящим дом-ом, а это произойдёт уже после подсчёта FCP и LCP или параллельно.
Увы, это может (может != обязательно будет) влиять на TBT - total blocking time, которая сейчас становится в общем-то основной метрикой для гугла.
Собственно, раз он сразу выдаёт документ со статикой - то именно от размера самого этого документа и будет зависеть FCP, а не от дополнительных скриптов. Вдвойне это чувствуется, когда классы вшивают в документ.
P.S. конечно мы не говорим об ошибках проектирования, например, когда из-за разницы дом-ов нужно перестраивать реальный или LCP картинка грузится не в приоритете или из клиентской логики.
Я конечно понимаю, что web vitals с недавних пор участвуют при приоретизации сайтов в поисковой выдаче, но всё же это только в гугле. Когда я захожу на статью про SEO оптимизацию я ожидаю немного почитать про SEO. Здесь ни о чём кроме производительности речь не идёт.
Ожидалось про семантику, про то, как метатеги добавляются - где их можно добавить, как они потом мерджатся (при добавлении из разных мест); как работает Link от некста и зачем им своя реализация и почему везде нужно использовать её; почему они рекомендует пре-рендеринг, а не какой-нибудь серверный рендеринг и зачем сделали инкрементальный рендеринг в альтернативу серверному для сайтов с большим количеством страниц.
В общем хоть про что-нибудь помимо производительности или не брать в название столь обширную тему, думаю про производительность читало бы не меньше людей, чем про SEO
Для статей используйте, пожалуйста, универсальный инструмент, который не зависит от вкусов вашей машинки - https://pagespeed.web.dev/ Сравнил vuestorefront и vercel - в среднем в обоих случаях 72 балла на мобилке, на десктопе у vercel 95 баллов. copilot.github.com - ужасный костыль (при всём уважении), грузящий и на десктопе и в мобильной версии картинки png в оригинальном качестве и выполняющий кучу логику на клиенте. В общем-то как и все остальные примеры, по содержимому можно устраивать конкурс на худшую реализацию. --- Вообще, реальная проблема next - то, что они модерируют примеры не по качеству, а по имени. Увы. (если кому интересно, то речь о странице https://nextjs.org/showcase) --- К счастью, на конфе с последнего релиза показали две действительно классные (в плане производительности) реализации - Pagespeed insights monogram.io - под 100 баллов на мобильных устройствах и macstadium.com - сейчас ~80, но раньше было также быстро (и по графику реальных пользователей видно, что 99% зеленые).
monogram.io, за 10 проверок выпадало от 82 до 99 баллов на мобильных устройствахmacstadium.com среди реальных пользователей
Отчасти вы правы, поэтому перед метриками стоит дисклеймер: Метрики приведённые ниже никак не отражают действительности в отношении производительности конкретных вариантов. Примеры приведены только для того, чтобы показать относительную скорость и пользовательский опыт от взаимодействия с сайтом в контексте темизации.
А в контексте приведенных примеров дела обстоят примерно так. (Буду использовать условные единицы для обозначения трудозатрат) При совпадении темы в SPA: Загрузка приложения (10у.е.) -> определение темы на клиенте (1у.е.) -> рендер приложения (8у.е.) = 19у.е. При несовпадении темы в SPA: Загрузка приложения (10у.е.) -> определение темы на клиенте (1у.е.) -> рендер приложения (8у.е.) = 19у.е.
При совпадении темы в SSG: Загрузка приложения (14у.е.) [мы грузим дополнительно весь html] -> определение темы на клиенте (1у.е.) -> сравнение реального и виртуального dom (2у.е.) [все совпадает, ничего дальше не происходит] = 17у.е. При несовпадении темы в SPA: Загрузка приложения (14у.е.) [мы грузим дополнительно весь html] -> определение темы на клиенте (1у.е.) -> сравнение реального и виртуального dom (2у.е.) -> ререндер клиентской части приложения (4у.е.) = 21у.е.
Повторюсь, это работает так только для конкретного примера - все зависит от проекта. И даже сложные проекты могут повторять ситуацию описанную выше (когда после определения клиентских данных приложение должно быть перерендерено).
А вообще, в идеале, тема должна быть полностью абстрагирована от кода, но все-таки обычно это не так.
Судя по вашему комментарию ("1 раз для первой загруженной страницы, а далее всё через клиента" -это может означать только SPA на клиенте) вы подразумеваете next / nuxt / sapper. В таком случае ответ и да и нет. Да – полноценный рендер в html происходит только для первой страницы, это верно. Вместе с html придёт весь клиентский код для этой страницы и на клиенте создастся виртуальный дом, в дальнейшем все изменения на этой странице будут происходить на клиенте. Исключением могут быть ленивые компоненты. Нет – как написал выше - клиентский код приходит для текущей страницы. При переходе* на другую страницу с сервера будет получен объект, описывающий следующую страницу и также будет содержать полученные для этой страницы props-ы (например после обращения к БД или из файловой системы). Ленивые компоненты также загружаются по мере необходимости.
* Обычно (для этого есть дополнительная опция в api инструментов) это работает не при переходе на другую страницу, а при наведении на ссылку.
Нет, к сожалению, ночного режима на хабре нет. Но хаброжителей это не останавливает, и можно найти расширенные копии хабра. Одна из лучших реализаций описана в статьях Владислава Якушева: первая часть и вторая. "Мне 17 лет и я уже несколько месяцев делаю клон мобильного приложения Хабра, назвав его соответствующе, модно, со стилем и пафосной точкой в конце — habra. Получилось реализовать несколько фич, которых пока нет ни в официальном приложении из плей маркета, ни на самом сайте." Одной из фич является как раз темизация. Возможно вам будет интересно.
P.Sсам не пользуюсь, наверно слишком привык к интерфейсу оригинальной версии
Статья впитала воды восторга по ходу написания. Возможно из-за слишком неожиданного релиза. Ждал серверные компоненты от react, буквально за несколько дней до релиза была потребность в серверной части, которую неплохо решают middleware. Да и performance budget тоже задумывался завести, а они добавили интеграцию в Vercel (checkly).
Хотя очень жаль, что она воспринимается как попытка продать. Фразы "сделаем веб быстрее" и "веб будущего" это цитаты из презентаций (которые все-таки обоснованы). Но тот самый момент лишь для тех, что задумывался о переходе на next.js, но что-то его не устраивало или чего-то не хватало. В статье нет посыла, что это единственно верный инструмент и он лучше всего на рынке. Это лучший и самый крупный релиз фреймворка next.js, о лидерстве в остальном судить не мне.
Нужен ли он вашему бизнесу – если никогда раньше о нем не думали и вообще никаких потребностей не было, то нет, не нужен. Он не стал принципиально новым, он лишь стал лучше. А если думали, то эта статья покажет, что изменилось и вы поймете – сможет теперь next решить ваши проблемы или все еще нет. В моем же случае он их решил и добавил много нового, чего ждал я и react комьюнити.
Ну так как это по умолчанию серверные компоненты (а страницы всегда стоит держать серверными, иначе нельзя будет настроить для них мета-заголовки), то можно сделать просто общий роут и в нём возвращать либо один компонент, либо другой (код на коленке):
Ну а когда сайт полностью статический - должно хватить generateStaticParams (но думаю раз раньше не хватило getStaticPaths - скорее всего и это не поможет)
-----
А как проверяли какой вариант возвращать в кастомном роутере?
Добрый!
Не, путь и параметры самое базовое API и просить оборачивать все страницы с контекст для такого - ужасный DX (да и не везде вообще есть такая возможность). Пакет использует внутреннее API next.js.
headers включает режим серверного рендеринга, поэтому мы от него отказались и не используем в компонентах.
А почему нельзя сразу обойтись стилями и всё? Зачем это делать логикой?
Если компонент завязан на клиента и стилями никак не решить - делаем его только клиентским:
-------
Пара условий, которые могут помочь в разных похожих ситуациях.
И так проверяет - клиентский компонент или серверный next.js использует внутри проверку:
Для проверки где сейчас рендерится клиентский компонент:
По багам не вписалось в статью, поэтому оставлю это в комментариях.
В 11 версии было решено завести i18n решение от next.js в коммерческий проект. Пара недель работы и… Странный баг, что вариант /en/en/page-name отображался как /page-name и разные артефакты от этого.
Как так вышло? Next.js проверял путь на наличие региона в начале и удалял его. Но эта логика повторялась примерно в десятке мест. Его удалось исправить в ядре, но оказалось, что для дефолтной локали всё ещё хуже и это не единственный артефакт. Как итог - откат.
Это произошло при тысячах тестов. Увы, но часто баги возникают именно на грани связок подобных параметров (таких как basePath, assetsPrefix, i18n).
Предположу, что этот функционал стал слишком провальным, так как next.js в новой версии даже не упоминает его и предлагает это делать через динамический сегмент (часть пути, в качестве которой могут быть разные варианты, в данном случае, например /[lang]/page-name) и middleware (как по итогу и было сделано в проекте).
Я делал относительно нормальный пет проект на нём. И первое время как-то нравилось - буквально plug-n-play - бери и делай, но вот с инпутом, кнопками и прочим с большим количеством условий (когда для элемента в css было бы 40 строк, а здесь это 40 классов) - как-то прям оттолкнуло.
Next.js уже лет 5 как не только про SSR, сейчас в первую очередь это про SSG с инкрементальной пересборкой.
А про 5 секунд действительно приукрасил, да. Знаете за сколько загружается эта страница на медленном 3g (что всё ещё является обыденным в мире и Европе)? 20 секунд, из которых 15 до загрузки LCP.
Быстрый 3g грузит страницу 5-10 секунд.
Остальной мир это не про гигабит в секунду.
Facebook, вероятно, это сделал, чтоб трафик сэкономить, т.к. экономия 2кб со страницы на миллионы (или миллиарды?) пользователей и переходов - весомая экономия на серверах.
Вряд ли там вообще упоминались улучшение метрик и SEO-оптимизация.
Про SSR речи и не идёт - да и там другие проблемы бы были важнее, вроде долгого ожидания начала загрузки документа, что при хорошем интернете обычно даже дольше, чем сама загрузка.
А сайты продумываются для всех - многие заходят на страницу лишь единожды. А первый вход важен для маркетинговых задач. Если пользователь первый раз грузил страницу 5 секунд, устал и ушёл, то уже неважно, что данные у него закешировались и дальше всё будет грузиться быстро.
(Когда речь идёт об оптимизациях таких мелочей, обычно это не про веб-приложения, а про маркетинговые сайты)
Бывает и такое, конечно, но имелось ввиду html документ со вшитыми стилями (т.е. когда стили не в отдельных файлах, а в теге <style />, в самой странице)
(контекст был про "экономия на большой html")
Удобство ломается с диким грохотов об блоки чуть сложнее карточки с закруглениями.
Когда для инпута нужно писать 10 классов на стили, по 5 классов на каждое состояние (hover, visites, disabled, ..., error), 15 классов на адаптив и ещё на всякий случай снаружи принимаешь классы, а то мало ли чего, ещё 20 классов нужно будет передать...
Да, при весе в 100кб сжатыми уменьшит на 5кб (если стили вшиты, например, а может и до 10кб, а может и 1 с трудом накапает, зависит). Это не меняет кардинально метрики, но, например, освобождается 5мб под прочее, может спрайт добавить внутрь? Да и 5кб + доли секунды в упрощении компрессии-декомпрессии сыграют в 1-2 балла (мы всё-таки ориентируемся на мобильные устройства).
А зачем их читать? В режиме разработки можно настраивать генерирование классов по другому (пакет это поддерживает из коробки). В продакшене ты залезаешь обычно просто конкретный элемент подправить, скорее ради интереса.
С картами и сентри очень хороший пункт, Спасибо! Вдруг тут кто-то обходил подобное и может поделиться решением?
А для автотестов классы больно и ненадёжно, атрибут всё же несравним. Мне больше всего нравится подход, когда этот атрибут добавляется во время сборки только в одном окружении, не в проде. Но такое не всем годится. Для накликивания можно было бы тоже сжимать классы только в проде, а все эти махинации проводить на тестовых стендах...
Стоит ли оно того, если есть другие минусы? Пожалуй нет;
Стоит ли это попробовать? Почему бы и да. 1 день на аб тесте или ручное сравнение на тестовом стенде даст ответы, есть ли достаточный эффект.
P.S. Как не плюсануть коммент выше за хороший развёрнутый коммент?
CSS in JS ужасен, да, поэтому речь только о CSS-модулях. Сам Next.js тоже перестал рекомендовать css-in-js решения и сейчас везде говорят только про css/scss/sass и css-модули (ну ещё бывает tailwind, но с кем не бывает).
А сайты бывают и сложнее приложений, современным компаниям для продвижения и анализа нужно куда больше, чем просто текст и красивая анимация.
Да, плохая формулировка, спасибо!
Имелось ввиду форматы, когда классы добавляются не по полноценному БЭМ-у (в котором есть сам класс и его модификаторы), а просто общие классы, то есть когда может быть:
<div class="card section box pt-20 mb-8" />
Это bootstrap и tailwind, например. Но если bootstrap устроен всё-же по БЭМ-у, то tailwind просто огромный набор атомарок, который у меня язык не поворачивается назвать БЭМ-ом (и выглядит это порою очень страшно).
Кто-нибудь, объясните мне, как это вообще выжило...
И до, и после (но в меньшем соотношении, да). Видел примеры, где эффект в сжатом виде стремительно приближался к нулю.
В самом худшем случае это небольшая разгрузка сервера и клиента, так как алгоритмам нужно проходить меньше символов. В лучшем - оптимизация. Вероятно будут страницы, где эффект хороший, а будут, где достаточно незаметный.
Если есть безобидный способ, пусть даже незначительно, сократить вес страницы, то почему бы и да.
Провожу много времени в попытках оптимизации сайтов. Пробовал svelte, шаблонизаторы, статику, и... они не дали явных преимуществ (особенно по сравнению с next.js v14 и серверными компонентами).
Всё это - виртуальный дом, множество логики, доп. библиотеки, в контексте next.js не влияют на FCP и LCP, так как Next в первую очередь выдаёт статику, и уже потом на клиенте, грубо говоря, виртуальный дом свяжется с настоящим дом-ом, а это произойдёт уже после подсчёта FCP и LCP или параллельно.
Увы, это может (может != обязательно будет) влиять на TBT - total blocking time, которая сейчас становится в общем-то основной метрикой для гугла.
Собственно, раз он сразу выдаёт документ со статикой - то именно от размера самого этого документа и будет зависеть FCP, а не от дополнительных скриптов. Вдвойне это чувствуется, когда классы вшивают в документ.
P.S. конечно мы не говорим об ошибках проектирования, например, когда из-за разницы дом-ов нужно перестраивать реальный или LCP картинка грузится не в приоритете или из клиентской логики.
Я конечно понимаю, что web vitals с недавних пор участвуют при приоретизации сайтов в поисковой выдаче, но всё же это только в гугле. Когда я захожу на статью про SEO оптимизацию я ожидаю немного почитать про SEO. Здесь ни о чём кроме производительности речь не идёт.
Ожидалось про семантику, про то, как метатеги добавляются - где их можно добавить, как они потом мерджатся (при добавлении из разных мест); как работает Link от некста и зачем им своя реализация и почему везде нужно использовать её; почему они рекомендует пре-рендеринг, а не какой-нибудь серверный рендеринг и зачем сделали инкрементальный рендеринг в альтернативу серверному для сайтов с большим количеством страниц.
В общем хоть про что-нибудь помимо производительности или не брать в название столь обширную тему, думаю про производительность читало бы не меньше людей, чем про SEO
Для статей используйте, пожалуйста, универсальный инструмент, который не зависит от вкусов вашей машинки - https://pagespeed.web.dev/
Сравнил vuestorefront и vercel - в среднем в обоих случаях 72 балла на мобилке, на десктопе у vercel 95 баллов.
copilot.github.com - ужасный костыль (при всём уважении), грузящий и на десктопе и в мобильной версии картинки png в оригинальном качестве и выполняющий кучу логику на клиенте. В общем-то как и все остальные примеры, по содержимому можно устраивать конкурс на худшую реализацию.
---
Вообще, реальная проблема next - то, что они модерируют примеры не по качеству, а по имени. Увы. (если кому интересно, то речь о странице https://nextjs.org/showcase)
---
К счастью, на конфе с последнего релиза показали две действительно классные (в плане производительности) реализации - Pagespeed insights monogram.io - под 100 баллов на мобильных устройствах и macstadium.com - сейчас ~80, но раньше было также быстро (и по графику реальных пользователей видно, что 99% зеленые).
Отчасти вы правы, поэтому перед метриками стоит дисклеймер: Метрики приведённые ниже никак не отражают действительности в отношении производительности конкретных вариантов. Примеры приведены только для того, чтобы показать относительную скорость и пользовательский опыт от взаимодействия с сайтом в контексте темизации.
А в контексте приведенных примеров дела обстоят примерно так. (Буду использовать условные единицы для обозначения трудозатрат)
При совпадении темы в SPA:
Загрузка приложения (10у.е.) -> определение темы на клиенте (1у.е.) -> рендер приложения (8у.е.) = 19у.е.
При несовпадении темы в SPA:
Загрузка приложения (10у.е.) -> определение темы на клиенте (1у.е.) -> рендер приложения (8у.е.) = 19у.е.
При совпадении темы в SSG:
Загрузка приложения (14у.е.) [мы грузим дополнительно весь html] -> определение темы на клиенте (1у.е.) -> сравнение реального и виртуального dom (2у.е.) [все совпадает, ничего дальше не происходит] = 17у.е.
При несовпадении темы в SPA:
Загрузка приложения (14у.е.) [мы грузим дополнительно весь html] -> определение темы на клиенте (1у.е.) -> сравнение реального и виртуального dom (2у.е.) -> ререндер клиентской части приложения (4у.е.) = 21у.е.
Повторюсь, это работает так только для конкретного примера - все зависит от проекта. И даже сложные проекты могут повторять ситуацию описанную выше (когда после определения клиентских данных приложение должно быть перерендерено).
А вообще, в идеале, тема должна быть полностью абстрагирована от кода, но все-таки обычно это не так.
Судя по вашему комментарию ("1 раз для первой загруженной страницы, а далее всё через клиента" - это может означать только SPA на клиенте) вы подразумеваете
next
/nuxt
/sapper
.В таком случае ответ и да и нет.
Да – полноценный рендер в html происходит только для первой страницы, это верно. Вместе с html придёт весь клиентский код для этой страницы и на клиенте создастся виртуальный дом, в дальнейшем все изменения на этой странице будут происходить на клиенте. Исключением могут быть ленивые компоненты.
Нет – как написал выше - клиентский код приходит для текущей страницы. При переходе* на другую страницу с сервера будет получен объект, описывающий следующую страницу и также будет содержать полученные для этой страницы props-ы (например после обращения к БД или из файловой системы). Ленивые компоненты также загружаются по мере необходимости.
* Обычно (для этого есть дополнительная опция в api инструментов) это работает не при переходе на другую страницу, а при наведении на ссылку.
Нет, к сожалению, ночного режима на хабре нет.
Но хаброжителей это не останавливает, и можно найти расширенные копии хабра. Одна из лучших реализаций описана в статьях Владислава Якушева:
первая часть и вторая.
"Мне 17 лет и я уже несколько месяцев делаю клон мобильного приложения Хабра, назвав его соответствующе, модно, со стилем и пафосной точкой в конце — habra. Получилось реализовать несколько фич, которых пока нет ни в официальном приложении из плей маркета, ни на самом сайте."
Одной из фич является как раз темизация. Возможно вам будет интересно.
P.S сам не пользуюсь, наверно слишком привык к интерфейсу оригинальной версии
Статья впитала воды восторга по ходу написания. Возможно из-за слишком неожиданного релиза. Ждал серверные компоненты от react, буквально за несколько дней до релиза была потребность в серверной части, которую неплохо решают middleware. Да и performance budget тоже задумывался завести, а они добавили интеграцию в Vercel (checkly).
Хотя очень жаль, что она воспринимается как попытка продать. Фразы "сделаем веб быстрее" и "веб будущего" это цитаты из презентаций (которые все-таки обоснованы). Но тот самый момент лишь для тех, что задумывался о переходе на next.js, но что-то его не устраивало или чего-то не хватало. В статье нет посыла, что это единственно верный инструмент и он лучше всего на рынке. Это лучший и самый крупный релиз фреймворка next.js, о лидерстве в остальном судить не мне.
Нужен ли он вашему бизнесу – если никогда раньше о нем не думали и вообще никаких потребностей не было, то нет, не нужен. Он не стал принципиально новым, он лишь стал лучше. А если думали, то эта статья покажет, что изменилось и вы поймете – сможет теперь next решить ваши проблемы или все еще нет. В моем же случае он их решил и добавил много нового, чего ждал я и react комьюнити.