Transcription
Всем привет, NexJ S16 здесь, и я собираюсь провести вас через него. Итак, в этой новой версии есть несколько действительно больших обновлений как на уровне NexJS, так и на уровне React, на которые мы посмотрим. Но в целом, я думаю, это серьезное улучшение. Так что обязательно посмотрите все видео, чтобы получить хорошее представление о том, что изменилось. Итак, у них есть пост в блоге, описывающий некоторые изменения. Но позвольте мне на самом деле просто показать вам здесь, в IDE, некоторые из вещей, которые действительно изменились. Итак, давайте на самом деле просто перейдем к этому. Я хочу начать совершенно новое приложение Nex.js. Итак, мы все еще можем использовать MPX create next app. К тому времени, когда вы это смотрите, вы, возможно, уже используете последнюю версию для версии 16. Однако на момент записи она все еще находится в бета-версии. Так что мне приходится использовать здесь бета. И я хочу все в текущем каталоге. Итак, теперь у нас здесь новая настройка. Итак, у них есть рекомендуемые настройки по умолчанию вместо того, чтобы нажимать пять опций или около того. У вас есть только один вариант, который вы можете выбрать здесь, и он будет использовать некоторые настройки по умолчанию. И они используют здесь шаблон. И теперь это закончено. И давайте посмотрим. Итак, нет папки исходного кода. У нас есть только папка приложения, но все остальное должно выглядеть знакомо. Итак, давайте на самом деле запустим наше приложение nextjs. Мы все еще можем запустить mpm rundev. И [хмыкает] давайте откроем это. Хорошо. Итак, вот новая домашняя страница. Похоже, это тоже новый шаблон здесь, на домашней странице. Итак, я удалил кучу шаблонного кода и сделал его больше похожим на реальное приложение. Итак, давайте на самом деле посмотрим на другие вещи, которые изменились здесь. Итак, я удалил шаблонный код по умолчанию и сделал его больше похожим на список постов, и вы можете отправить один. Мы поговорим об этом подробнее через секунду. Но если я перейду на домашнюю страницу, я обновлю здесь. Если мы на самом деле посмотрим на логирование, мы увидим, что это тоже изменилось. Итак, вместо того, чтобы давать вам одно число, теперь оно разбивает его по времени, которое потребовалось для компиляции этого маршрута, и времени, которое потребовалось для рендеринга. И если у вас есть промежуточное ПО или то, что теперь называется прокси, мы поговорим об этом через секунду. Это тоже показывает вам это. Итак, теперь оно лучше разбито, чтобы вы могли лучше определить, почему определенные вещи занимают больше времени. Потому что раньше некоторые люди жаловались, что NextJS был медленным. В некоторых из этих случаев это было на самом деле потому, что рендеринг их страницы просто занял немного больше времени. Так что теперь легче определить, куда тратится время, чтобы подготовить его для пользователя. Хорошо. И это теперь собирается по умолчанию с Turboac. Так что Turboac стал стандартом для разработки, но также и для вашего производственного билда. Так что, если я запущу билд здесь, он должен показаться вам быстрее. И вы также увидите время, которое потребовалось для каждого из этих шагов здесь. Так что у вас больше видимости и в этом. Итак, о turbopac, это, по сути, сборщик для ваших приложений nextg. Раньше это был webpack. Так что сборщик позволяет нам, по сути, ну, разбивать наш код на разные файлы, верно? Так что я импортирую вещи из других файлов здесь или модулей. И все это в какой-то момент объединяется сборщиком, верно? Так что я могу экспортировать вещи из других файлов и импортировать их в этот файл. И сборщик также выполняет разделение кода. Так что он разделяет его по индексу маршрута. Так что на домашней странице он загрузит код для этой страницы. Так что мы не обязательно загружаем код страниц, которые мы никогда не посетим. И он также, если вы импортируете только одну функцию из файла, он не будет включать весь остальной код из этого файла в конечный вывод. Так что он также выполняет некоторую тряску дерева. И в XJS у нас есть use client, верно? Так что часть кода должна идти в браузер, а часть кода должна оставаться на сервере. Так что это различие также делается сборщиком. И если вы запустите билд, он также убедится, что ваши файлы минифицированы и, по сути, оптимизированы и так далее. И в целом, да, с TurboAC, он должен быть намного быстрее. Итак, было много твитов о том, насколько быстрее все стало. Многие люди сообщали о довольно значительном, о довольно значительном приросте производительности. Так что, если вы обновляетесь до Next S16, то при запуске билда во многих случаях он будет значительно быстрее. Итак, некоторые люди сообщали о 50% быстрее. Вот человек, который перешел с 2 минут 15 секунд до 30 секунд. Так что здесь действительно огромные преимущества в производительности. Это поместит вывод билда сюда, в next. И здесь на самом деле есть новая папка под названием dev. И это на самом деле предназначено для кодирующих агентов. Так что, если вы использовали этих кодирующих агентов или, верно, у меня есть гилоты. У меня также есть кодеки здесь, возможно, вы используете cloth code. По сути, эти кодирующие агенты очень хотят запустить билд. По сути, они вносят кучу изменений в код, а затем они как бы хотят проверить, что то, что они сделали, ничего не сломало. Так что им нравится запускать билд, потому что во время билда также проверяются типы. Есть некоторое линтинг. Так что, по сути, это простой способ для них проверить, что они ничего не сломали в приложении. Однако, если вы уже запускаете сервер разработки, а затем ваш кодирующий агент запускает билд, это может вызвать конфликт, и, возможно, вы с этим сталкивались. Так что теперь они добавили папку dev, и это должно помочь с этой проблемой. Так что теперь должно быть меньше конфликтов между вашими кодирующими агентами и вашим сервером разработки. Хорошо. Теперь, что, если у вас есть приложение, и вы хотите добавить к нему промежуточное ПО. Ну, на самом деле это изменилось. Так что теперь это не называется промежуточным ПО. Оно было переименовано в прокси. Так что вам нужно создать файл с именем proxy.ts. И затем вам также нужно экспортировать функцию с именем proxy. Так что раньше это называлось промежуточным ПО, но оно было переименовано в прокси. Оно работает так же, но переименование в основном, я думаю, чтобы сигнализировать разработчику, что это не совсем то же самое, что промежуточное ПО, к которому вы, возможно, привыкли из других фреймворков, таких как Express или других фреймворков. Так что обычно не рекомендуется делать здесь такие вещи, как делать вызовы к базе данных, например, где вам нужно пройти через сеть, по сути, операции ввода-вывода или выполнять здесь длительные задачи или сложные вычислительно интенсивные вещи. Верно? Так что это не для этого. Идея здесь в том, чтобы использовать это для легких быстрых перенаправлений, например, или перезаписи. Так какие примеры вещей, которые вы могли бы сделать здесь? Так что, возможно, есть входящий запрос на ваш слэш-обаут, но вы хотите добавить некоторый локальный индикатор к URL. Так что вы можете перезаписать URL, прежде чем продолжить. Или, возможно, вы проводите какое-то A/B тестирование, поэтому вам нужно перезаписать URL для этого. Или, возможно, у вас есть какая-то многопользовательская настройка, где вы используете приложение на другом субдомене. Но затем для вызовов API запрос должен использовать другой URL в зависимости от клиента, и, возможно, обнаружение ботов, например, если это легковесно и быстро, вы можете попробовать добавить это сюда, в прокси. Теперь, что насчет аутентификации? Это немного серая зона. Так что, если вы выполняете аутентификацию с помощью сеансов базы данных, где вам нужно сделать вызов к вашей базе данных, чтобы понять, имеет ли пользователь доступ или нет, ну, это, вероятно, не рекомендуется добавлять сюда, верно? Так что мы не хотим делать сетевые вызовы из этого места. Но что, если у вас есть стратегия JSON Web Token, где, по сути, вся информация находится в JSON Web Token? В этом случае нам не нужно обращаться к нашей базе данных, вся информация будет доступна нам здесь. Можете ли вы тогда выполнить аутентификацию в промежуточном ПО или прокси? Ну, я бы сказал, что это все еще не рекомендуется. Например, возможно, у вас есть компонент в вашем приложении, который извлекает данные, и только вошедшие в систему пользователи должны иметь возможность просматривать эти данные. Ну, если вы используете этот компонент внезапно на другой странице и забываете обновить сопоставитель здесь, не вошедшие в систему пользователи смогут просматривать данные, верно? Так что это будет работать только для домашней страницы прямо сейчас. Так что, если вы извлекаете данные из своей базы данных на другой странице, это не будет работать. Так что, если у вас есть проверка аутентификации, если вы делаете это здесь, это не будет работать, когда вы на самом деле хотите этого. Если вы выполняете проверку аутентификации здесь, вы всегда должны помнить, что сопоставитель здесь совпадает с тем, где вы на самом деле получаете доступ к данным в вашем приложении. И я бы сказал, что довольно часто вы забываете. Так что, если вы случайно извлекаете данные в другом компоненте, и этот компонент затем используется на другой странице, вы можете забыть обновить сопоставитель. И особенно если вы работаете в команде людей, некоторые люди могут просто использовать этот компонент где-то еще на другой странице, и внезапно это перестанет быть синхронизированным. Так что выполнение проверки аутентификации, промежуточного ПО или прокси здесь, вероятно, не рекомендуется для любой стратегии. Но тогда где вы должны выполнять аутентификацию? Ну, у меня есть другие видео об этом о том, что называется уровнем доступа к данным. Так что вы хотите иметь одно выделенное место в вашем приложении, где вы получаете доступ ко всем данным в вашей базе данных, и вы хотите связать проверку аутентификации или авторизации с извлечением данных, так что прямо перед тем, как вы фактически получите доступ к данным, у вас будет эта проверка, чтобы увидеть, авторизован ли пользователь для доступа к нему, а затем использовать только функции из этого уровня доступа к данным. Так что везде, где вы используете эту функцию в вашем приложении, на любой странице, в любом компоненте, всегда будет проверка аутентификации. Верно? Это лучшая архитектура, на мой взгляд. Так что я бы сказал, что аутентификация в прокси, вероятно, нет. Есть некоторые исключения. Так что, если у вас есть журнал или веб-сайт типа блога, и вы хотите, чтобы страницы оставались статически отрисованными, как это называется, использование уровня доступа к данным, вероятно, сделает их динамически отрисованными. Так что в этом случае единственное решение, которое я видел до сих пор лично, это фактически выполнить аутентификацию в прокси. Это может сохранить ваши страницы статически отрисованными. Это немного сложная тема. Так что у меня будет отдельное видео об этом скоро. Так что, если вы хотите сохранить статическое рендеринг страниц, которые находятся за логином. Так что, например, статья только для платных участников, то в этом случае, я не знаю другого способа сохранить ее статически отрисованной. Так что это может быть исключением. Или вы хотите иметь оптимистичное перенаправление. Так что есть входящий запрос на секретную страницу, и только вошедшие в систему пользователи должны иметь к ней доступ. Ну, у меня есть основная проверка аутентификации на уровне доступа к данным. Но, возможно, по какой-то причине я хочу получить очень быстрый ответ на это. Так что я уже могу иметь оптимистичное перенаправление здесь, чтобы быстро проверить, есть ли у пользователя вообще токен, например, и если нет, мы можем немедленно перенаправить их сюда, прежде чем делать что-либо еще в приложении. Так что это может быть исключением. Но я бы сказал, что правило — не выполнять аутентификацию. Это немного сложная тема, и у меня скоро будет отдельное видео об этом. Есть также некоторые улучшения с предварительной выборкой. Так что они упомянули дублирование макета, а также инкрементальную предварительную выборку. Так что, чтобы показать вам, что такое предварительная выборка в nextJS. Если я добавлю сюда ссылку на страницу, этот компонент ссылки, я ссылаюсь на /about здесь, я ставлю это в самом конце, затем, если я прокручу туда, и это попадет в поле зрения, ничего не произойдет здесь во время разработки. Но если я запущу билд, mpm run build. И теперь я хочу запустить этот билд, мне нужно запустить mpm run start. Так что теперь я запускаю билд здесь. Если я теперь прокручу до конца и медленно, но верно доведу его до поля зрения, вы можете увидеть, как только он попадет в поле зрения, он фактически сделает запрос на получение этой страницы или, я бы сказал, React server component, верно? Страница на самом деле просто React компонент. Это серверный компонент, и вы можете видеть, что он был получен. Так что предварительная выборка включена по умолчанию в производстве, но вы не увидите ее в разработке. Так что вам на самом деле нужно запустить билд, а затем использовать mpm run start, чтобы фактически увидеть предварительную выборку. Теперь представьте, что это был бы нижний колонтитул со 100 ссылками, верно? Так что у вас есть некоторые веб-сайты, у них много ссылок в нижнем колонтитуле. Так что вы хотите быть немного осторожны с поведением предварительной выборки. Вы можете фактически установить его в false, если хотите. Так что есть способы настроить его. Но они внесли некоторые другие улучшения здесь. Так что дублирование макета. Так что у вас может быть файл макета здесь, верно? Так что у вас может быть вложенный макет. Так что, если у вас есть конкретный макет для нижнего колонтитула, и у вас есть эти 100 ссылок, они используют один и тот же макет, тогда они, возможно, все предварительно выбрали этот макет. Так что это теперь дублируется. Но затем они также отменяют запросы, когда ссылка покидает поле зрения. И они приоритизируют предварительную выборку ссылок при наведении. Так что, когда вы фактически наводите на нее мышь или когда она снова попадает в поле зрения, они также будут предварительно выбирать их снова, если их данные недействительны. И у нас будет что-то под названием кешируемые компоненты. Я расскажу об этом через секунду. Так что, по сути, куча улучшений здесь для предварительной выборки, и это может привести к большему количеству индивидуальных запросов на предварительную выборку, но общий размер передачи данных обычно должен быть меньше, и они думают, что это правильный компромисс для почти всех приложений. И это не требует модификации кода и должно улучшить производительность ваших приложений. И затем есть также некоторые изменения в кешировании. Теперь я знаю, когда я начинаю говорить о кешировании и nextjs, некоторые из вас пугаются, но на самом деле я думаю, что это скоро все упростит. Так что на самом деле есть некоторые изменения, и я думаю, что их стоит немного понять. Так что, если у вас есть какая-то страница здесь, верно, домашняя страница, что я здесь делаю? У меня просто список постов. В настоящее время у меня только один пост в моей базе данных. Так что я получаю все эти посты из моей базы данных здесь. И я просто отображаю их здесь в списке, верно? Так что в URL здесь я просто прохожу по ним, верно? Очень базовое извлечение данных здесь в Nex.js, верно? Из моей базы данных серверный компонент. Так что я могу сделать все здесь. И у меня также есть форма. Так что пользователь может создать новый пост. Так что здесь у меня есть форма. И если я скажу тест и напишу тест, я должен иметь возможность нажать опубликовать. И когда я это делаю, вы можете видеть, что он фактически отправлен. И я также почти сразу вижу, как он появляется здесь в пользовательском интерфейсе без обновления. Так как это работает? Ну, это делается с помощью серверного действия, верно? Так что здесь у меня есть действие, это создать пост. Так что это использует серверное действие здесь. Так что данные этой формы фактически отправляются на мой сервер next.js здесь, и мы можем получить заголовок и содержимое, а затем мы можем просто добавить их в нашу базу данных. Хорошо. Так что пост является частью моей базы данных. Но это не значит, что пользовательский интерфейс фактически меняется, верно? Так что, если мы хотим этого, мы можем фактически использовать revalidate path. Это на самом деле очень мощный API, потому что, когда данные идут из браузера сюда, на наш сервер, это запрос, а затем в рамках ответа мы можем немедленно отправить обновленный пользовательский интерфейс с новым сообщением в блоге. Так что, если я покажу вам это, если я скажу тест два, и я скажу тест два, если я опубликую это, вы можете видеть, что есть запрос из браузера на сервер. Так что с серверными действиями это фактически просто пост по маршруту, который вы их используете, так что это на домашней странице здесь, и вы можете видеть в полезной нагрузке, что он отправляет данные из формы в рамках этого запроса, верно? И затем здесь в ответе это выглядит как абракадабра, но на самом деле это просто описание того, каким должен быть новый пользовательский интерфейс. В том же цикле запроса-ответа мы также обновили пользовательский интерфейс. Кстати, что еще я делал здесь? Ну, очень часто мы хотим выполнить кучу дополнительной работы с нашими данными. Так что в этом случае, когда пользователь отправляет новый пост, я хочу, например, выполнить некоторое SEO-обогащение этого поста, получить правильный SEO-заголовок и SEO-описание автоматически для этого поста. Я, возможно, хочу создать переводы этого поста, чтобы я мог обслуживать другую версию или разные локали. Я, возможно, захочу проверить спам или другие конфиденциальные детали в посте. И, возможно, я хочу проиндексировать его для поиска, верно? Возможно, я хочу создать некоторые вложения, чтобы люди могли эффективно искать этот пост. Так что, по сути, я хочу выполнить кучу дополнительной работы над этим постом. И это очень распространено в реальном мире. Если вы создаете что-то немного более сложное, чем просто чистое демо-приложение, вы увидите, что вам часто нужно выполнять много этой дополнительной работы. И это немного сложно сделать в Nex.js. Next.js действительно построен вокруг очень быстрого цикла запроса-ответа, верно? Так что мы, верно, мы получаем входящий запрос и быстро возвращаем что-то пользователю. Так что мне на самом деле очень понравилось использовать Mosha для этого. Они спонсируют канал, но они делают это очень просто, например, для выполнения кучи фоновых заданий. Так что я просто делаю вызов API, чтобы запустить этот рабочий процесс. И когда Mosha закончит, это может занять несколько минут, но он вызовет обратно мое приложение, чтобы сообщить мне, что он закончил. В этот момент я могу обновить пост в базе данных с дополнительными данными, которые мне нужны о нем. А пока я уже могу быстро дать ответ пользователю, верно? Я покажу вам больше об этом позже. на самом деле очень интересно. Я знаю, что многие из вас хотят выполнять фоновые задания, и это действительно, это действительно сложно сделать в X.js, но я покажу вам больше об этом через секунду. Я просто быстро хотел дать вам пример других реалистичных вещей, которые мы обычно хотели бы сделать здесь, но позвольте мне просто быстро объяснить, как работает это кеширование. Отлично. Так что это действительно мощно, но есть и небольшой недостаток или пара. Так что мы теперь инвалидируем кеш для всей страницы, верно? Так что у нас могут быть другие вещи на странице, которые на самом деле не затронуты новым постом. Так что мы сбрасываем кеш для всей страницы. И также, мы можем фактически иметь эти посты и на другой странице. Вы можете представить, что у нас может быть страница дашборда, где мы показываем последние посты, пять последних постов, скажем, и это также может быть закешировано. И поэтому мы хотели бы сбросить этот кеш. Так что произойдет, я думаю, есть некоторые новые вещи в Nex.js с кешированием. это будет выглядеть немного иначе. Так что у нас будет функция, например, которую мы можем вызвать get post, верно? Так что мы можем просто сделать это, верно? Вот как я бы извлекал данные, но у нас будет новая директива, которую вы будете видеть чаще, и это будет директива use cache. Мы говорим NextJS, что результат этой функции должен быть закеширован. Где бы мы ни извлекали данные на домашней странице или на странице дашборда, результат этого кешируется, и мы можем дать ему тег, чтобы мы могли также инвалидировать, и мне все еще нужно импортировать таким образом, как при записи, но я могу как бы пометить этот кеш именем, идентификатором, просто называемым posts, что имеет смысл. Так что везде, где я использую get posts, будь то на домашней странице или на странице дашборда или где-либо еще, где я хочу показать список постов, он будет закеширован, но затем позже, например, потому что есть новый пост, я могу использовать это имя тега, чтобы инвалидировать кеш. Так что в этом случае я не только хочу перевалидировать домашнюю страницу, это просто одна страница, но мы можем фактически извлекать данные на других страницах. Так что везде, где используется эта функция, я хочу инвалидировать или перевалидировать ее. Так что есть функция rev validate tag. Так что у нас есть немного более точный контроль над этими данными и их поведением кеширования. Так что у нас уже есть rev validate tag, но здесь есть одно изменение, которое заключается в том, что теперь есть второй параметр, и мне нужно указать какой-то срок жизни кеша. Так что, по сути, некоторая информация о том, как он должен быть закеширован. Они рекомендуют max для большинства случаев, насколько я читал. Теперь я покупаю этот кеш постов везде, где я получаю посты. Так что я думаю, вы увидите это часто. Вы будете помечать что-то как закешированное. Вы дадите ему какой-то тег, который позволит вам получить точный контроль над тем, когда его следует инвалидировать. И затем вы можете использовать revalidate tag. Теперь это дает вам то, что они называют поведением "still while revalidate". Так что, что это значит, есть новый пост в базе данных, и мы очищаем кеш для поста. Так что в следующий раз, когда кто-то просмотрит пост, изначально он все равно будет обслуживать старые посты. Так что устаревшие посты, можно сказать, потому что это быстрее. Так что в первый раз, когда кто-то зайдет сюда, это будут старые посты, а затем в фоновом режиме он получит последние. Это максимально быстро. Но теперь у нас также есть новая функция под названием update tag. Так что это новое, и мы можем использовать ее только в серверных действиях. И что мы можем сделать здесь, это получить другой шаблон, другое поведение, называемое "read your right". Так что теперь, когда мы добавляем новый пост в нашу базу данных, update tag в этом случае, в следующий раз, когда кто-то просмотрит посты на нашей странице, мы не будем показывать им устаревшие данные, мы просто получим последние данные из R. Так что мы не будем обслуживать ничего из кеша, мы фактически обратимся к нашей базе данных в этом случае и получим данные. Это означает, что это может занять немного больше времени, потому что здесь изначально он просто будет обслуживать старые данные из кеша, так что это быстрее, а затем в фоновом режиме он получит последние. Так что позже, в какой-то момент, это все равно будут свежие данные, но изначально это будут устаревшие данные. Так что это просто быстрее, но устаревшие данные. Здесь это медленнее, потому что пользователь фактически должен ждать, пока мы не получим данные из нашего источника данных. Так что это медленнее, но точнее. Это быстрее, не так точно. Так что, если вы хотите более быстрого поведения для ваших данных, вы, вероятно, захотите использовать validate tag, и вам нужно указать этот новый срок жизни кеша. Они описали это в документации, варианты, но обычно это будет max. Однако, если точность является самым важным для вашего приложения, вы обычно хотите использовать update tag, верно? Так что я думаю, что эта комбинация маркировки тегом, извлечения данных, а затем инвалидации кеша с помощью validate tag или update tag будет очень распространенной. Так что теперь, если я попытаюсь отправить этот тест шесть, я пробовал другие вещи. Если я нажму опубликовать сейчас, вы можете видеть, что он также появляется здесь в пользовательском интерфейсе для меня. Похоже на то, что было раньше, revalidate path, но теперь у нас есть более точный контроль. Теперь, если он не появляется в пользовательском интерфейсе или у вас есть другая ситуация, когда вы хотите обновить пользовательский интерфейс, есть также refresh, и на самом деле это предназначено для того, что они называют динамическими данными. Так что, если вы фактически извлекаете какие-то данные, и они не закешированы, но вы все еще хотите обновить пользовательский интерфейс, вы можете использовать этот refresh. Это на самом деле предназначено как серверный аналог того, что у вас было на стороне клиента с роутером, вы можете сделать router.refresh refresh на стороне клиента, но вы можете фактически вызвать это непосредственно с сервера после обновления данных, а также другое, что изменилось здесь, на самом деле частичный предварительный рендеринг. У меня было несколько видео об этом, и многим из вас это очень понравилось, но это на самом деле меняется, и просто чтобы быстро recap, по сути, когда вы запускаете билд, как мы видели здесь, билд, он фактически будет генерировать статические страницы, верно? Так что, по сути, здесь у меня есть домашняя страница, он попытается создать HTML из этого, а затем мы можем поместить его на CDN. И тогда, когда кто-то зайдет туда или много людей зайдет туда, мы можем немедленно обслужить страницу, верно? Нам не нужно выполнять никаких вычислений здесь, HTML уже готов. Это оптимально. И вы можете видеть, когда вы запускаете билд, что именно это он делает. Он даже покажет вам для каждого маршрута, является ли он статическим, верно? Так что он был предварительно отрисован и готов к работе, или динамическим. Но обычно мы хотим, чтобы он оставался статически отрисованным, потому что это самый быстрый возможный опыт для пользователя. Это невозможно, если у вас, например, есть заголовок здесь, и вы выполняете какое-то, например, это что-то с аутентификацией. Так что, возможно, вы хотите показать аватар пользователя, вошедшего в систему, верно? Так что вы будете проверять их куки на JSON Web Token или какую-либо другую информацию, и вы хотите отобразить эту информацию на странице. В этом случае вы используете куки или заголовки или что-то еще. В этом случае страница не будет статически отрисована, потому что она зависит от информации времени выполнения, верно? Так что она зависит от входящего запроса. Нам нужно знать это, прежде чем мы сможем фактически отрисовать страницу, верно? Я не знаю, кто зайдет на страницу, когда я запущу билд здесь. Так что мы не можем предварительно отрисовать страницу для чего-то подобного. Так что она будет автоматически исключена из статического рендеринга в динамический рендеринг. Так что это была проблема, потому что для такого маленького элемента, как этот, вся страница превращалась бы в динамический рендеринг, даже если это всего лишь этот маленький кусочек, этот маленький островок, можно сказать, эта информация времени выполнения. Так что с PPR, с частичным предварительным рендерингом, идея в том, что вы можете обернуть его в suspense. По сути, пометить границу между этой частью, которой требуется это динамическое поведение. Остальная часть страницы, оболочка вокруг нее, может по-прежнему статически отрисовываться, но только эта часть здесь может оставаться динамически отрисованной. И это была идея частичного предварительного рендеринга. И я думаю, что это все еще поведение. Но я думаю, что большая часть этого поведения кеширования будет унифицирована в том, что они называют кешируемыми компонентами. И будут некоторые различия в реализации. И будут дополнительные функции, верно? Так что, например, этот use cache также является частью кешируемого компонента. Так что большая часть этого поведения кеширования, я думаю, будет унифицирована в этом кешируемом компоненте, и они упоминают, что больше об этом будет документировано и объявлено до выпуска. Верно? Так что на момент записи это все еще бета-версия, но скоро должно быть больше информации об этом. Если вы уже хотите использовать такие вещи, как use cache, вам нужно включить опцию cache components is true в next config, и на самом деле я увеличил это до канареечной версии. Так что бета-версия сама по себе не имела этого. Так что мне пришлось перейти на канареечную версию на nextg 16. Так что, если вы хотите попробовать это, но я бы не слишком беспокоился о кешировании. Будет большое обновление, похоже, и я создам отличное видео об этом скоро, когда это обновление появится, чтобы у вас была ясная картина того, как все это работает. Так что убедитесь, что вы подписаны, и вы получите уведомление, когда это видео появится. Есть также некоторые большие изменения на уровне React. На самом деле, это также может действительно улучшить ваши приложения. Так что теперь он поддерживает React compiler, который стабилен. Так что, вы можете видеть здесь в блоге React, версия один теперь доступна, и мы также можем использовать ее в Nex.js. Так что нам просто нужно добавить React compiler в наш файл конфигурации здесь, и нам нужно установить этот плагин для Babel. Так что это зависит от Babel, и они упоминают, что вы должны ожидать, что время компиляции в разработке и во время билдов будет выше при включении этой опции, потому что этот React compiler зависит от Babel. Хорошо. Теперь, что вы получаете за это? Ну, что делает React compiler? Ну, самое главное, он может автоматически оптимизировать ваше React-приложение с помощью этой автоматической мемоизации. Так что в React вы, возможно, использовали хук use memo, верно? Так что, если вы выполняете какой-то тяжелый расчет в вашем компоненте, так что здесь, например, мы сортируем массив, если это большой массив или сложный массив или выполняем сложную сортировку, каждый раз, когда этот компонент рендерится, без use memo, нам пришлось бы выполнять сортировку снова и снова, верно? Так что это нехорошо для производительности, так что с use memo мы можем просто сортировать один раз, а затем каждый раз, когда этот компонент повторно рендерится, мы можем просто продолжать использовать тот же результат, конечно, если некоторые из зависимостей здесь изменятся, мы хотим сортировать снова, это уменьшит количество времени, которое нам нужно сортировать, верно? Сортировка — это лишь один пример, но, по сути, мы можем избежать множества тяжелых вычислений, выполняемых снова и снова ненужным образом с помощью use memo, верно? Так что это use memo. Теперь есть также use callback. Так что, если вы помещаете функцию здесь, просто в теле компонента, она будет воссоздаваться каждый раз, когда компонент рендерится. Это неэффективно, и особенно если вы используете ее как зависимость где-то, возможно, зависимость use effect, она будет рассматриваться как другая функция каждый раз. Мы могли бы обернуть ее с помощью use callback, чтобы вы получили только одну функцию. Она просто не обязательно воссоздается снова и снова. И есть также react.m memo. Так что это вы можете обернуть свой компонент этим. Так что по умолчанию React компонент повторно рендерится, если его родитель повторно рендерится. Но если пропсы компонента не меняются, мы не хотим его рендерить. Так что мы могли бы обернуть его в react. Memo, верно? Так что до этого момента нам приходилось вручную определять те места и писать их самим. Большое обещание здесь с React compiler заключается в том, что он может делать это автоматически для нас. И они фактически упоминают, что в большинстве случаев эта мемоизация будет такой же точной или даже более точной, чем то, что вы могли бы написать сами. Так что это действительно мощно, и они рекомендуют для нового кода полагаться на компилятор для минимизации и использовать эти хуки только там, где вам действительно нужен точный контроль. Теперь, что насчет вашего существующего кода? Можете ли вы просто удалить все эти use memos? Они рекомендуют оставить существующую минимизацию на месте. Удаление может изменить вывод компиляции, или если вы собираетесь удалить ее, вам нужно быть осторожным и провести много тестирования до и после удаления. Так что на самом деле большое обновление, и оно может действительно улучшить производительность определенных React-приложений, особенно тех, которые выполняют много тяжелых вычислений в определенных компонентах. Хорошо. И next 16 также будет поддерживать React 19.2. Так что 19.2 вышел ранее в этом месяце и на самом деле имеет некоторые действительно интересные обновления. Теперь, краткое уведомление. Если вы делаете MPX create next app, а затем бета-версию, она фактически установила React 19.1.1 для меня. Так что, если вы хотите использовать последнюю версию, они также упоминают эту команду. Так что React at latest и React DOM at latest. И тогда вы должны получить 19.2. Теперь, почему вы захотите обновиться до 19.2? Ну, одна из вещей, которые мы теперь получаем, это несколько переходов. Так что это позволяет нам создавать действительно красивые анимации здесь, почти как будто вы находитесь в мобильном приложении. Это помогает нам создавать впечатления, которые так же плавны и приятны, как и то, что вы видите во многих мобильных приложениях. И традиционно такие анимации немного сложно сделать в Интернете. С этими переходами вы можете легче создавать действительно красивые впечатления здесь. И способ работы заключается в том, что вы используете компонент few transition. Так что здесь вы просто оборачиваете это в few transition, а затем, когда этот компонент рендерится на странице, верно? Так что здесь, если я нажму кнопку, компонент элемента будет отрисован. Если я нажму сейчас, вы можете видеть, что у него фактически есть анимация по умолчанию. Вы можете настроить это с помощью пропсов. Но по умолчанию он будет затухать и появляться вот так. Но есть куча необязательных пропсов, которые вы можете использовать, чтобы указать, как он должен себя вести. И есть также новый компонент activity, который также решает проблему, с которой вы, вероятно, сталкивались раньше с React. Вы можете представить, что у меня есть что-то в этой боковой панели здесь. Если я нажму на это, состояние изменится, верно? Так что у меня есть обзор, который открыт сейчас. Верно, сейчас я закрываю боковую панель. Теперь ее нет. Но если я снова открою ее, вы можете видеть, что мы потеряли это состояние. Верно? Так что теперь мне нужно снова нажать на эту кнопку, чтобы открыть ее. Верно? Так что мы, по сути, когда мы удаляем боковую панель, мы теряем состояние, которое было внутри этой боковой панели. И что вы можете сделать, это обернуть эту боковую панель в компонент activity. Так что теперь, когда вы это делаете, когда я открываю этот обзор здесь, теперь, когда я фактически скрываю боковую панель, ее состояние будет сохранено. Теперь, когда я открываю ее, она все еще там, верно? Так что мы можем как бы сохранить это внутреннее состояние, когда оно удалено. И способ, которым React делает это за кулисами, это фактически использование display none в CSS. Так что он не полностью удаляет это из DOM. Он просто использует некоторый CSS, чтобы удалить его из того, что мы видим, что позволяет ему сохранить состояние. Есть также новый хук use effect event. Так что, когда у вас есть use effect здесь, и внутри этого use effect вы используете переменную под названием URL, тогда вам нужно добавить ее в массив зависимостей. Верно? И это означает, что каждый раз, когда это меняется, функция в use effect здесь будет запускаться снова. Верно? Так что это все стандартное поведение. Если у меня есть другая переменная там, может быть, я использую количество элементов. Если бы я использовал это здесь, тогда мне пришлось бы добавить это в массив зависимостей. Так что тогда каждый раз, когда количество элементов менялось бы, это перезапускалось бы. Теперь иногда это не то, что вы хотите, верно? Так что, если количество элементов меняется здесь, может быть, я не хочу, чтобы оно перезапускалось. Так что в этом случае вы можете извлечь эту часть логики и обернуть ее здесь в use effect event. Так что в этом случае я регистрирую посещение с некоторым URL и этим количеством элементов. В этом случае я использую только URL, верно? Так что количество элементов здесь находится вне user fact. Так что мне не нужно указывать его здесь. Немного сложно, но, по сути, способ разделить реактивные части и вещи, которые действительно должны реагировать, и нереактивные части, вещи, которые мы не хотим вызывать какую-либо реакцию. Теперь некоторые другие вещи на самом деле, требования к версии для NexJS 16 вам нужна более новая версия NodeJS. Так что NodeJS 18 больше не поддерживается. Это в основном актуально, я думаю, если вы самостоятельно размещаете NexJS. Я на самом деле снимал видео о самостоятельном размещении на VPS, и VPS с Coolifi фактически использовал старую версию по умолчанию, и поэтому версия NexJS16 не работала. Так что мне пришлось обновить версию NodeJS на этом VPS. Так что посмотрите мое другое видео об этом. Теперь о самой версии NexJS. Так что прямо сейчас мы уже на версии NexJS 16. Теперь кто-то спрашивал об этом, почему вышел основной релиз версии, и генеральный директор Forcell упомянул, что они строги. Так что, если вы задавались этим вопросом, вот почему мы уже на версии 16. Для меня это не проблема, но я могу представить, что вы можете начать чувствовать себя немного отстающим, если последняя версия уже опережает вас, но это потому, что они строги. Теперь позвольте мне на самом деле показать вам, что я делаю здесь с Moshia. Так что, когда пользователь отправляет пост, мы создаем пост в нашей базе данных, но мы даем ему статус "обрабатывается", потому что мы на самом деле хотим получить другую информацию о том, что пользователь отправил в заголовке и содержимом. Вы можете представить, что мы хотим получить какой-то сводку о посте в блоге и теги для поста, чтобы его было легче искать, например. Есть куча работы, которую мы хотим сделать с этим постом. Но нам не нужно делать это прямо сейчас. Нам не нужно прерывать пользовательский опыт. Мы можем просто быстро дать ответ пользователю, а затем выполнить эти задачи в фоновом режиме. Теперь, если вы когда-либо пытались сделать что-то подобное самостоятельно, вы знаете, что это немного сложно сделать в Nex.js. Next.js действительно построен вокруг очень быстрого цикла запроса-ответа. Он не очень хорошо подходит для длительных задач, таких как фоновые системы или системы очередей или cron-задания. Так что на самом деле я передаю это здесь. Я отправляю это на свой экземпляр Mosha. Moshia спонсирует канал. Я отлично провел время, используя их. Они являются частью программы open source. Так что вы можете найти их здесь на GitHub. Так что именно туда я отправляю свои посты. Так что на самом деле очень приятно, что у меня может быть мое, можно сказать, фронтенд-подобное приложение next.js здесь. А затем для всех фоновых заданий я использую Mosha в этом случае. Mosha — это просто отдельное приложение, вызов API. И мы можем просто отправить вызов API в Mosha, Mosha сделал это очень простым для создания такого рабочего процесса. И вот мое приложение Mosha. Вот мое приложение next. И давайте я покажу вам, как это работает. Я запущу их оба, верно? Так что очень распространенно иметь, скажем, фронтенд и бэкенд приложение в одном рабочем пространстве. Так что я запущу мое приложение NexJS с этой стороны, а затем у меня есть приложение Moshia с этой стороны. Теперь, что я получаю с этим, когда я теперь отправляю пост? Так что теперь, если я отправляю пост, я опубликую этот пост здесь. Вы можете видеть, что я получаю этот ответ здесь в пользовательском интерфейсе очень быстро. Но теперь в фоновом режиме мой рабочий процесс MOSA работает над его обогащением, локализацией, встраиванием, созданием вложений для поиска. И затем, когда он закончен, он финализирован. Мое приложение next JS здесь, обновление здесь. Все прошло хорошо. И это, итак, мое приложение next JS получает обновленный пост здесь с заголовком и содержимым по-прежнему. Но теперь у него также есть сводка. Хорошо, это теги, переводы, и я могу получить все это, не загромождая мое приложение next JS, верно? Так что я могу отделить этот фоновый рабочий процесс от моего приложения NextJS. Так что здесь, в Moshia, это работает с шагами. Так что в React все является компонентом. В Moshia все является шагом. И это очень легко создать этот рабочий процесс. Так что, например, он начинается с шага API. Так что мы можем фактически запустить рабочий процесс. Мы можем сделать HTTP-запрос и запустить его. Так что здесь он просто получает входящий запрос. Так что здесь я могу указать тип шага, что это API, и он предназначен просто как способ запустить рабочий процесс. Мы можем указать путь, верно? Так что здесь в моем приложении next мне нужно отправить HT, мне нужно отправить запрос на /ost, потому что это то, что я указываю здесь. Это должен быть POST-запрос. И я также могу указать входящие данные. Какую форму они должны иметь? На самом деле он использует Zot для этого. Так что здесь у меня есть моя схема Z, верно? Так что он получит этот входящий пост. Он испускает событие. Есть другие шаги, которые будут подписаны на него. Так что, когда это событие происходит, они начнут работать. Так что есть событие post created, и другой шаг подписывается на него. Так что здесь я выполняю SEO-обогащение поста, и оно выполняется, когда происходит событие post created. Здесь у меня есть логика. Так что я получаю эти данные поста и отправляю их в OpenAI. OpenAI, мы спрашиваем OpenAI, эй, можете ли вы обогатить этот пост дополнительными данными? Это может занять несколько секунд. На самом деле, если вы используете последние модели с AI, иногда это может занять несколько минут. Это было бы довольно неловко вставлять в приложение next JS. Но здесь я могу просто сделать это в фоновом режиме. В конце концов, это закончено, и я снова испускаю событие. Что пост теперь обогащен. Так что, затем у меня есть другой шаг, который имеет дело, который подписался на это событие. Так что это локализованный шаг. Так что он может выполнять некоторые переводы, например, но он также хочет перевести SEO-данные. Так что ему нужно дождаться, пока это событие произойдет. Так что здесь мы могли бы отправить его в AI. Я просто сплю 4 секунды, чтобы имитировать, сколько времени это займет примерно, но это просто добавит данные к посту и испустит событие. Так что после локализации мы можем проиндексировать этот пост для поиска, возможно, создать вложение, сохранить его в векторном хранилище, и это испустит событие. И затем, в конечном итоге, это закончено, и у меня есть один финальный шаг. И что это сделает, это просто сделает вызов API обратно в мое приложение next.js снова с дополнительными данными, которые оно смогло сгенерировать здесь, в этом рабочем процессе. Так что теперь здесь в пользовательском интерфейсе, если я отправляю пост, я получаю очень быстрый ответ здесь, но я все еще могу видеть, просто чтобы показать, что это обрабатывается в фоновом режиме. Теперь Mosha обогащает его, локализует, добавляет вложения для поиска, вы знаете, может быть, несколько минут. Это Mosha, вызывающий обратно в приложение next.js. Так что мое приложение next JS может предоставить обработчик маршрута API. мой, верно, next JS6 обработчик маршрута API/MOSHA он получит этот веб-хук от MOSHA, и мы можем просто обновить в нашей базе данных, статус завершен в этом случае, и помните, что эти посты закешированы. Затем, когда Mosha закончит, что может занять несколько минут, нам нужно снова обновить кеш. Так что теперь, как я показываю вам, у нас есть новый update tag, но его можно использовать только в серверных действиях. Так что здесь, в обработчике маршрута, где часто нужно инвалидировать кеш, потому что вы получаете какой-то веб-хук от, ну, Motion в этом случае или какой-то CMS. Так что вам нужно иметь возможность инвалидировать кеш. Так что в этом случае вам придется использовать validate tag или revalidate path, но validate tag немного более точный. Так что это более реалистичная настройка, потому что в более сложном приложении вы часто хотите выполнять кучу работы в фоновом режиме. Вы можете представить, что если мы хотим сделать что-то по расписанию, как cron-задание, это также было бы немного неловко вписать в приложение nextjs, но с motion это был бы просто один шаг, и вы также получаете действительно отличную наблюдаемость здесь. Так что здесь у вас есть рабочее место, и оно покажет вам, сколько времени заняли эти шаги. Так что я связываю эти шаги, а затем, когда у вас есть фактический запуск этого, вы получаете наблюдаемость здесь. Так что я вижу, что локализация здесь заняла довольно много времени. Так что я могу нажать на нее и получить некоторые детали. Я могу видеть, сколько времени это заняло и какое событие оно испускает. Теперь, если этот шаг завершится с ошибкой с Mosha, мы можем фактически автоматически повторить шаг. Так что вы получаете кучу надежности, которая бы Теперь, если вы хотите попробовать Mosha, вы можете просто запустить эту команду здесь, которую вы можете найти на их домашней странице, и вы получите базовую настройку здесь, чтобы вы могли осмотреть и получить представление о том, как это работает. Вы также получаете действительно приятную визуализацию здесь, в рабочем месте, кстати. Так что здесь, в этой настройке по умолчанию, я вижу обзор моего рабочего процесса здесь. Это все шаги, верно? Так что, если я задаюсь вопросом, эй, что происходит на этом шаге снова? Какой здесь снова код? Я могу осмотреть это прямо здесь. Я немного увеличил масштаб, и здесь я использую TypeScript, но если у кого-то в вашей команде есть больше опыта работы с Python, вы можете фактически использовать Python. Вы можете иметь некоторые шаги на TypeScript, некоторые шаги на Python. У меня будет больше видео с Mosha в будущем, но я рекомендую вам проверить их. Вы можете найти ссылку в описании. В любом случае, я надеюсь, это поможет вам с последним Nex.js. В нем много всего, но если вы будете в курсе, это не так уж плохо. И я скоро создам еще одно видео о всей системе кеширования в Nex.js. Так что следите за обновлениями. Убедитесь, что вы подписаны. В любом случае, надеюсь, это поможет вам, и спасибо за просмотр. И я надеюсь увидеть вас в следующем. Пока.