Transcription
[Музыка] Добро пожаловать на полный курс по Next.js. В этом курсе вы узнаете всё, что вам нужно знать о Next.js, от основ до более продвинутых концепций. К концу курса вы сможете уверенно создавать быстрые и масштабируемые приложения с помощью Next.js. Если вы искали всеобъемлющий, простой в освоении, хорошо организованный и практический курс, который проведет вас от нуля до героя, то это правильный курс по Next.js для вас. Вам не нужны никакие предварительные знания Next.js, чтобы начать. Все, что вам нужно, есть здесь, так что вам не придется перескакивать туда-сюда между случайными учебниками. Но вот в чем загвоздка: в отличие от других курсов, мы не просто создаем демонстрационное приложение. Мы будем создавать красивое полнофункциональное приложение производственного уровня для отслеживания проблем. Приложение с полным набором функций и паттернов пользовательского интерфейса, которые вы ожидаете от современных приложений. На главной странице у нас есть эта красивая панель управления, которая отображает последние проблемы и их статус. И все эти данные хранятся в базе данных MySQL. Мы можем перейти на страницу проблем, мы можем фильтровать проблемы, сортировать их и переходить на разные страницы. Мы можем нажать на проблему, чтобы увидеть больше деталей. Мы можем назначить проблему пользователю. Итак, здесь у нас полная аутентификация и авторизация. Мы можем редактировать проблему, и здесь у нас этот красивый редактор Markdown. Мы также можем удалить проблему, и здесь мы получаем это диалоговое окно подтверждения. Мы будем создавать это приложение, используя передовой стек: Next.js 13, Tailwind, Radix UI, Prisma, React Query, React Hook Form, Zod и многое другое. И не волнуйтесь, если некоторые из этих инструментов вам незнакомы. Как и в моих других курсах, я проведу вас через каждый из них, объясняя что, почему и как. Так что, если вы будете следовать за мной, вы освоите Next.js и сможете уверенно создавать полнофункциональные приложения. Я инженер-программист с более чем 20-летним опытом, и я научил миллионы людей программировать и становиться профессиональными инженерами-программистами через мой YouTube-канал и онлайн-школу codewithmarsh.com. Если вы здесь впервые, обязательно подпишитесь, так как я постоянно загружаю новые видео. А теперь давайте приступим и начнем. [Музыка] Хорошо, так что именно вам нужно знать, чтобы пройти этот курс? Ну, чтобы пройти этот курс, вам не нужны никакие предварительные знания Next.js, потому что я собираюсь научить вас всему с нуля. Однако вам нужно иметь базовое знакомство с React и TypeScript, потому что Next.js — это фреймворк React. И если вы не знаете React, вы не совсем подходящий студент для этого курса. Теперь, если вы хотите изучить React, у меня есть отличный учебник на моем YouTube-канале. Ссылка находится под этим видео. У меня также есть всеобъемлющий курс, который выходит далеко за рамки этого. Он учит вас всему, что вам нужно знать, чтобы создавать современные приложения с React 18 и TypeScript. Полный курс длится 14 часов и разделен на две части, так что вы можете легко закончить каждую часть. В этом курсе вы научитесь создавать это красивое приложение для поиска видеоигр. Здесь у нас есть все распространенные паттерны пользовательского интерфейса, которые вы видите в реальных приложениях, такие как фильтрация, сортировка, бесконечная прокрутка и так далее. Опять же, если вы заинтересованы, ссылка находится под этим видео. Добро пожаловать обратно на наш курс Next.js. В этом разделе мы поговорим об основах Next.js. Сначала я объясню, что именно такое Next.js и почему он так популярен. Вскоре после этого мы настроим нашу среду разработки и создадим наш первый проект Next.js. Оттуда мы поговорим о некоторых фундаментальных концепциях, таких как клиентские и серверные компоненты, получение данных, кэширование, а также статический и динамический рендеринг. Этот раздел является отличным введением в Next.js, так что давайте приступим и начнем. [Музыка] Итак, вы, возможно, задаетесь вопросом, что это за Next.js, о котором все говорят, и почему мне стоит этим заниматься? Ну, Next.js — это невероятно мощный фреймворк для создания быстрых и дружественных к поисковым системам приложений. Он построен поверх React, поэтому все, что вы узнали о React, по-прежнему актуально. Но Next.js выводит веб-разработку на новый уровень. В то время как React — это просто библиотека для создания интерактивных пользовательских интерфейсов, Next.js — это всеобъемлющий фреймворк. Думайте о фреймворке как о наборе библиотек, инструментов и соглашений, которые упрощают разработку приложений. Например, Next.js включает свою собственную библиотеку маршрутизации, поэтому нам не нужно использовать отдельную библиотеку, такую как React Router. С точки зрения инструментов, он поставляется с компилятором для преобразования и минимизации нашего JavaScript-кода, интерфейсом командной строки для сборки и запуска нашего приложения, а также средой выполнения Node.js. Теперь вы можете спросить, что именно такое среда выполнения Node.js? Ну, есть два основных способа выполнения JavaScript-кода: либо в веб-браузере на стороне клиента, либо в среде выполнения Node.js на сервере. Итак, среда выполнения Node.js — это просто модный термин для программы, которая может выполнять JavaScript-код. Таким образом, Next.js поставляется со средой выполнения Node.js, и это позволяет нам делать действительно крутые вещи. Первое — это то, что мы можем заниматься полнофункциональной разработкой. Мы можем писать как фронтенд, так и бэкенд код в одном проекте Next.js. Бэкенд код выполняется в среде выполнения Node.js, а фронтенд код собирается и отправляется клиенту для выполнения в веб-браузере. В отличие от этого, при создании приложений с React нам приходится поддерживать отдельный бэкенд-проект и, возможно, на другом языке программирования. Эта среда выполнения Node.js также позволяет нам рендерить наши компоненты на сервере и отправлять их содержимое клиенту. Этот метод называется серверным рендерингом или SSR и может сделать наши приложения быстрее и дружественнее к поисковым системам. Мы поговорим об этом подробно позже в курсе. Но подождите, это еще не все. С Next.js мы можем предварительно рендерить определенные страницы и компоненты, которые имеют статические данные. Когда мы собираем наше приложение, мы просто рендерим их один раз и обслуживаем их всякий раз, когда они нужны. Этот метод называется генерацией статических сайтов и может сделать наши приложения супер быстрыми. Итак, в двух словах, Next.js — это фреймворк для создания супер быстрых и дружественных к поисковым системам приложений. [Музыка] Хорошо, а теперь давайте поговорим о настройке нашей среды разработки. Для запуска Next.js у вас должна быть установлена версия Node 16.8 или выше. Так что зайдите на nodejs.org и скачайте последнюю версию. Теперь в этом курсе я буду использовать VS Code в качестве своего редактора. Как и в моих других курсах, вы можете использовать свой предпочтительный редактор, но я призываю вас использовать VS Code, потому что по ходу дела я буду делиться множеством советов и приемов для быстрого написания кода. Так что вы можете получить VS Code с code.visualstudio.com. Теперь здесь, в окне VS Code, давайте поговорим о расширениях, которые я собираюсь использовать в этом курсе. Итак, в этой панели найдите es7. Хорошо, посмотрите на это расширение: es7+ React, Redux, React Native. Это расширение предоставляет нам множество сниппетов кода, так что мы можем быстро и легко генерировать компоненты React. Следующее расширение — TypeScript. Это вот здесь: JavaScript and TypeScript Nightly. И последнее — Tailwind CSS IntelliSense. Теперь, если вы никогда раньше не работали с Tailwind, не волнуйтесь, это очень просто, и я буду держать вас за руку на протяжении всего курса. [Музыка] Хорошо, чтобы создать наш первый проект Next.js, откройте окно терминала и выполните npx create-next-app. Вы можете использовать последнюю версию, но в этом курсе я собираюсь использовать версию 13.4, поэтому я настоятельно рекомендую вам использовать ту же версию, чтобы у вас не возникло никаких трудностей при прохождении курса. Давайте приступим. Теперь он спрашивает, хотите ли вы установить этот пакет: create-next-app версии 13.4.13. Давайте продолжим. Хорошо, теперь он задаст нам кучу вопросов о нашем новом проекте. Первый вопрос — название нашего проекта. Я собираюсь использовать next-app. Следующий вопрос — хотите ли вы использовать TypeScript в этом проекте. Ответ по умолчанию — да, так что давайте нажмем Enter, чтобы принять его. Следующий вопрос касается использования ESLint, который является распространенным инструментом анализа кода, который мы можем использовать для поиска распространенных ошибок, таких как синтаксические ошибки, проблемы с форматированием и так далее. Опять же, мы примем значение по умолчанию, которое равно да. Следующий вопрос касается использования Tailwind CSS. Еще раз, мы примем да. Следующий вопрос касается использования каталога source. Многие проекты Next.js не используют каталог source, поэтому я выберу нет. Следующий вопрос касается использования нового App Router. Я расскажу об этом позже в этом разделе, но очень кратко: в Next.js 13 у нас есть два типа маршрутизаторов: у нас есть новый App Router и унаследованный Pages Router. В этом курсе мы будем использовать новый App Router, так что давайте выберем да. Последний вопрос касается настройки псевдонимов импорта по умолчанию. Мы выберем нет. Хорошо, теперь он установит все эти зависимости. Так что вы видите, у нас есть React, ReactDOM, Next, TypeScript и так далее. Хорошо, все наши зависимости установлены. Так что теперь давайте войдем в эту папку и выполним npm run dev. Это запускает сервер разработки на порту 3000. Так что давайте нажмем Ctrl и кликнем по этой ссылке, и это подтверждает, что наш первый проект Next.js открыт и работает. [Музыка] Давайте поговорим о ключевых файлах и папках в этом проекте. Итак, наверху у нас есть папка app, или это также называется App Router. Это контейнер для нашей системы маршрутизации. Итак, в Next.js наш маршрутизатор основан на файловой системе. Так что, в отличие от React Router, нам не нужно настраивать наши маршруты и сопоставлять их с нашими компонентами. Мы можем просто создавать файлы и папки для представления наших маршрутов. Мы поговорим о них в следующем уроке. Итак, в папке app у нас есть файл favicon, у нас есть наш глобальный файл CSS, файл layout, который является базовым компонентом React, возвращающим элементы html и body. Это представляет собой общий макет для наших страниц. Теперь внутри элемента body у нас есть children, который динамически заменяется страницей во время выполнения, в зависимости от того, где находится пользователь в нашем приложении. Теперь в этой папке у нас также есть файл page.tsx. Это представляет нашу главную страницу. Итак, для этой демонстрации давайте удалим все здесь и заменим его простым разметкой. Итак, мы вернем элемент main. Внутри main мы хотим добавить заголовок H1 и сказать "hello world". Теперь вернемся в браузер. Здесь у нас есть быстрая перезагрузка. Так что всякий раз, когда мы вносим какие-либо изменения в наши файлы TypeScript или CSS, изменения отражаются немедленно. Теперь здесь у нас есть небольшая проблема со стилизацией, потому что к элементу body применяется градиент, линейный градиент. Так что давайте перейдем к нашему глобальному файлу CSS. Внизу посмотрите на стили, примененные к элементу body. Атрибут background установлен на линейный градиент, и именно поэтому у нас есть этот странный стиль здесь. Так что просто удалите атрибут background, и проблема исчезнет. Красиво. Теперь я хочу применить здесь отступ, чтобы контент не был слишком близко к краям экрана. Так что давайте добавим отступ в один rem. Хорошо, это лучше. Так что мы закончили с папкой app. Теперь в этом проекте после этой папки у нас есть папка public. Здесь мы можем размещать наши статические ресурсы, такие как изображения. В данном случае у нас здесь два файла SVG, которые являются векторной графикой. Один — Next, другой — Vercel, которая является компанией, создавшей Next.js. Теперь в корне у нас есть куча конфигурационных файлов. У нас есть один для ESLint, другой для Next, PostCSS, Tailwind и TypeScript. По большей части нам не нужно касаться этих конфигурационных файлов, но если ситуация изменится в будущем, мы вернемся и пересмотрим их. Спасибо. [Музыка] Хорошо, я сказал вам, что маршрутизация в Next.js основана на файловой системе. Так что здесь, в папке app, мы можем создать новую папку под названием users. Теперь, чтобы сделать это общедоступным здесь, мы должны добавить файл page в эту папку. Итак, page.tsx. Теперь расширение может быть JS, JSX или TSX, или TypeScript. В этом курсе мы используем TypeScript, так что я выберу TSX. Теперь убедитесь, что вы назвали этот файл правильно: page в нижнем регистре, потому что это одно из соглашений, которое ищет Next.js. Итак, система маршрутизации в Next.js основана на соглашениях, а не на конфигурации. Хорошо, так что здесь у нас есть файл page. Теперь в этом файле page мы должны экспортировать компонент React, который будет рендериться, когда пользователь находится в этом месте /users. Ранее мы установили очень полезное расширение в VS Code. С помощью этого расширения мы можем сгенерировать компонент React, используя этот ярлык: rafce. Это сокращение от React Arrow Function Component with Export. Теперь, как я это запоминаю, это Raf C. Хорошо, так что это сгенерировано. Красиво. Теперь здесь у нас активировано несколько курсоров, так что мы можем переименовать этот компонент во что-то более осмысленное, например, UsersPage. Имя, которое мы здесь присваиваем, не имеет значения с точки зрения маршрутизации. Это просто для лучшей организации нашего кода. Хорошо, теперь давайте нажмем Escape, чтобы деактивировать несколько курсоров. Вернемся в браузер. Теперь давайте перейдем по адресу /users, и вот наша новая страница пользователей. Красиво. Теперь одна вещь, которую вам нужно знать об этой системе маршрутизации, это то, что если вы добавите любые другие файлы в эту папку, скажем, test.css, этот файл не будет доступен. Так что, если вы перейдете по адресу /users/test.css, посмотрите, мы получаем эту страницу "не найдено". Так вот чем новый App Router отличается от старого Pages Router. В Pages Router, если мы поместили какие-либо файлы в эти папки, эти файлы были бы общедоступны. Но это не так с новым маршрутизатором. Хорошо, так что давайте удалим этот файл. Теперь здесь мы также можем создавать вложенные маршруты. Так что внутри папки users мы можем добавить новую папку под названием new, и в этой папке мы добавляем новый файл page. Итак, page.tsx. Еще раз, давайте создадим компонент React, и мы назовем его NewUserPage. Хорошо. Так что теперь мы можем перейти по адресу /users/new и увидеть эту новую страницу. Красиво. Теперь давайте поговорим о навигации. Так что мы вернемся на нашу главную страницу. Так что здесь мы нажимаем Command+P на Mac или Ctrl+P на Windows, чтобы искать файлы по их имени. Если мы наберем page, мы увидим все наши файлы page. Так что первый элемент — это наша главная страница, это та, которую мы ищем. Теперь на этой странице давайте добавим якорь. Так что здесь у нас есть якорь. Мы устанавливаем href на /users и даем ему метку, например, Users. Теперь есть проблема с этим способом реализации навигации. Позвольте мне показать вам. Так что давайте вернемся на нашу главную страницу. Хорошо, теперь я открою DevTools здесь, на вкладке Network. Посмотрите на все запросы, отправленные на сервер. Первый — это наш HTML-документ, второй — шрифт, третий — файл CSS, а после этого у нас есть куча файлов JavaScript. Теперь я очищу этот список. Посмотрите, что происходит, когда мы нажимаем на ссылку Users. Давайте вернемся на вкладку Network. Посмотрите, все эти ресурсы перезагружаются. Это не оптимальный способ реализации навигации, потому что в реальном приложении у нас, вероятно, будет навигационная панель сверху, боковая панель слева. Так что, когда пользователь перемещается со страницы на страницу, мы не хотим перезагружать все эти повторяющиеся части. Мы хотим заменить только область контента, верно? Вот где мы используем компонент Link в Next.js. Так что вернемся к нашему коду. Мы собираемся заменить этот якорь компонентом Link, который определен в библиотеке next/link. Хорошо, давайте заменим его здесь тоже. Хорошо. Теперь вернемся на нашу главную страницу. Еще раз, я открою вкладку Network и очищу этот список. Теперь посмотрите, что происходит, когда мы нажимаем на ссылку Users. Посмотрите, у нас всего два запроса, и эти запросы предназначены для загрузки содержимого страницы Users. Мы не перезагружаем шрифт, файл CSS и кучу файлов JavaScript. Это то, что мы называем клиентской навигацией. Теперь есть еще кое-что о навигации. У нас есть всеобъемлющий раздел об этой теме позже в курсе. Это был просто базовый обзор. [Музыка] В проектах Next.js у нас есть две среды, где мы можем рендерить наши компоненты и генерировать HTML-разметку: либо на клиенте в веб-браузере, либо на сервере в среде выполнения Node.js. Рендеринг компонентов на клиенте похож на то, как работают приложения React. Мы называем этот метод клиентским рендерингом или CSR. С другой стороны, у нас есть серверный рендеринг или SSR, где компоненты рендерятся на сервере. Так в чем же разница? Ну, с клиентским рендерингом нам приходится собирать все наши компоненты и отправлять их клиенту для рендеринга. Это означает, что по мере роста нашего приложения растет и размер нашего пакета, потому что он должен содержать все наши компоненты. Теперь чем больше пакет, тем больше памяти нам нужно на клиенте для загрузки всех этих компонентов. Так что этот подход требует много ресурсов. Другая проблема заключается в том, что боты поисковых систем, которые являются машинами, просматривающими и индексирующими наши веб-сайты, не могут видеть наш контент, потому что они не могут выполнять JavaScript-код. Так что они не могут рендерить наши компоненты, как веб-браузер. И последнее, но не менее важное: любые конфиденциальные данные, которые у нас есть в наших компонентах или их зависимостях, такие как ключи API, будут раскрыты клиенту. Теперь, если мы рендерим наши компоненты на сервере, мы можем избавиться от всех этих проблем. Мы отправляем клиенту только необходимые компоненты и предотвращаем чрезмерное увеличение размера нашего пакета. Кроме того, поскольку сервер обрабатывает большую часть рендеринга, нам требуется меньше ресурсов на клиенте. Плюс, поскольку рендеринг выполняется на сервере, и мы отправляем фактический контент клиенту, боты поисковых систем могут видеть и индексировать наши страницы. И, наконец, мы можем хранить конфиденциальные данные, такие как ключи API, на сервере. Итак, это все большие преимущества серверного рендеринга. Однако с серверным рендерингом мы теряем интерактивность. Так что серверные компоненты, которые являются компонентами, рендерящимися на сервере, не могут слушать события браузера, такие как клик, изменение, отправка и так далее. Они не могут получить доступ к API браузера, таким как локальное хранилище. Они не могут поддерживать состояние или использовать эффекты. Эти функциональные возможности доступны только в клиентских компонентах. Так что в реальных приложениях мы часто используем смесь серверных и клиентских компонентов. Мы должны по умолчанию использовать серверные компоненты и использовать клиентские компоненты только тогда, когда они нам абсолютно необходимы. Вот пример. Давайте представим, что мы хотим создать страницу для отображения списка продуктов. Чтобы создать эту страницу, нам, вероятно, потребуется несколько компонентов, таких как navbar, sidebar, product list, product card, pagination и footer. Теперь в стандартных приложениях React нам приходится упаковывать все эти компоненты и отправлять их клиенту для рендеринга. Но в Next.js мы можем хранить все эти компоненты на сервере и минимизировать размер пакета. Есть только одно исключение: чтобы добавить продукт в корзину, нам нужно обработать событие клика кнопки. Обычно мы реализуем эту функциональность в компоненте ProductCard. Так что нам придется сделать его клиентским компонентом. Это один вариант. Но есть лучший способ. Мы можем оставить этот компонент на сервере и выполнять большую часть рендеринга там, а вместо этого извлечь небольшой компонент, который содержит только кнопку "Добавить". С этим изменением мы отправляем клиенту только этот крошечный компонент и оставляем все остальное на сервере. Давайте посмотрим на это в действии. Вернемся к нашему проекту. В Next.js все компоненты в папке app по умолчанию являются серверными компонентами. Так что это означает, что все страницы, которые мы создали до сих пор, это серверные компоненты, и они рендерятся на сервере. Позвольте мне показать вам. Так что вернемся в браузер. Давайте откроем вкладку Network и посмотрим на первый запрос. Это HTML-документ, который мы получаем с бэкенда. Так что посмотрите, у нас есть наш контент здесь. У нас есть наш "hello world" и ссылка на пользователей. Это именно то, что видят боты поисковых систем, когда они просматривают наш веб-сайт. В отличие от этого, если бы мы использовали клиентский рендеринг, как работают стандартные приложения React, боты поисковых систем не смогли бы увидеть наш контент. Они бы увидели пустую страницу, потому что все компоненты, весь контент рендерится на клиенте. Хорошо, так что вернемся к нашему проекту. Все компоненты в папке app по умолчанию являются серверными компонентами. Теперь, если вы раньше работали с Next.js, я должен упомянуть, что Pages Router не поддерживает серверные компоненты. Так что в дальнейшем вам следует прекратить его использовать и перейти на новый App Router. Хорошо, теперь давайте создадим здесь новую папку под названием components. Ранее я говорил вам, что эта папка не является общедоступной, если в ней нет файла page. Так что это означает, что мы можем совместно размещать файлы нашего проекта, такие как наши компоненты и другие строительные блоки, с нашими страницами. Мы можем разместить их рядом друг с другом, и это совершенно нормально. Так что здесь, в папке components, давайте добавим новый файл под названием ProductCard.tsx. Здесь мы создаем базовый компонент React. Ранее я говорил вам, что серверные компоненты не могут иметь интерактивности. Так что они не могут обрабатывать события браузера, такие как клик, изменение и так далее. Так что это означает, что если мы добавим сюда кнопку и обработаем событие клика, мы получим ошибку во время выполнения. Позвольте мне показать вам. Так что давайте передадим базовую функцию ошибки и выведем что-нибудь в консоль, и установим метку на "Add to Cart". Теперь давайте добавим этот компонент на нашу главную страницу. Так что мы переходим к нашему первому файлу page и добавляем наш новый компонент ProductCard. Теперь вернемся в браузер. Посмотрите, мы получили ошибку, гласящую: "Обработчики событий не могут быть переданы в props клиентских компонентов". Если вам нужна интерактивность, рассмотрите возможность преобразования части этого в клиентский компонент. Теперь у нас есть два варианта. Один вариант — сделать весь этот компонент клиентским компонентом. Так что мы идем наверх и используем директиву "use client". Так что в кавычках мы набираем "use client". Это все, что нам нужно сделать. Этим мы говорим компилятору Next.js включить этот файл или этот компонент в наш JavaScript-пакет. И это означает, что если этот компонент зависит от других компонентов, эти компоненты автоматически станут клиентскими компонентами и будут включены в наш JavaScript-пакет. Так что нам не придется повторять эту директиву на каждом клиентском компоненте. Хорошо, так что вот один вариант. Теперь, если вы вернетесь в браузер, ошибки не будет. Но есть лучший способ сделать наши приложения быстрее и дружественнее к поисковым системам. Мы хотим рендерить наши компоненты на сервере как можно больше и использовать клиентские компоненты только тогда, когда это абсолютно необходимо. Так что здесь наш ProductCard может иметь сложную разметку. Мы хотим рендерить всю эту разметку на сервере и переместить эту кнопку на клиент. Так что я собираюсь извлечь эту кнопку и поместить ее в отдельный компонент. Так что здесь, в папке components, давайте добавим новый файл: AddToCart. Опять же, мы создаем базовый компонент React. Наверху мы используем директиву "use client", а затем перемещаем эту кнопку в наш новый компонент вот так. Хорошо, так что теперь у нас есть клиентский компонент, и мы будем использовать его в нашем ProductCard. Хорошо, с этим мы можем удалить "use client" из этого файла. Так что этот компонент будет рендериться на сервере. И это означает, что там, где у нас есть клиентский компонент, в данном случае, где у нас есть эта кнопка, будет отверстие или слот, куда React позже вставит наш клиентский компонент. Хорошо, теперь, если вы вернетесь на главную страницу, опять же, мы не видим никаких ошибок. Так вот как мы можем создавать и использовать клиентские и серверные компоненты. Привет, ребята, я надеюсь, вам было весело смотреть этот учебник. Я просто хотел упомянуть, что этот учебник — первый час моего полного курса по Next.js. Так что после того, как вы закончите его, если вы хотите узнать больше, я настоятельно рекомендую вам записаться на полный курс, потому что он намного быстрее и проще, чем перескакивать между кучей случайных несвязанных учебников здесь на YouTube. Полный курс длится 5 часов и учит вас всему, что вам нужно для создания полнофункциональных приложений с Next.js. Он также поставляется с сертификатом об окончании и 30-дневной гарантией возврата денег. Так что, если вы не удовлетворены, попросите полный возврат средств. Вы получите все свои деньги обратно, без вопросов. Если вы заинтересованы, ссылка находится под этим видео. [Музыка] Теперь есть два способа получить данные: мы можем получить их на клиенте или на сервере. Чтобы получить данные на клиенте, мы обычно используем хук состояния для объявления переменной состояния и хук эффекта для вызова бэкенда, получения данных и помещения их в нашу переменную состояния. Теперь в моем курсе React я говорил о React Query как о лучшей альтернативе ручному использованию хуков состояния и эффекта. Но независимо от того, как мы получаем данные, получение данных на клиенте в клиентских компонентах имеет все проблемы, о которых мы говорили в предыдущем уроке. Так что со временем наши пакеты будут становиться больше, потому что нам приходится отправлять все больше и больше компонентов клиенту. Кроме того, этот подход требует много ресурсов, потому что весь рендеринг выполняется на клиенте. Плюс наш контент или наши данные не видны поисковым системам, и этот подход менее безопасен, потому что наши ключи API или любые конфиденциальные данные окажутся на клиенте. Но есть одна дополнительная проблема. Проблема в том, что с этим подходом всегда есть дополнительный круговой путь к бэкенду. Так что, когда приложение React загружается, сначала браузер загружает HTML-шаблон, а также файлы CSS и JavaScript с бэкенда. Затем он отправит дополнительный запрос для получения данных с бэкенда. Так что всегда есть дополнительный круговой путь к бэкенду. Но мы можем получать данные в наших серверных компонентах и избавиться от всех этих проблем. Позвольте мне показать вам. В этом уроке мы будем использовать JSONPlaceholder для получения некоторых фиктивных данных в наше приложение. Если вы не знакомы с JSONPlaceholder, это фиктивный API для получения некоторых фиктивных данных. Так что зайдите на jsonplaceholder.typicode.com. На этой странице вы найдете различные конечные точки для получения фиктивных данных, таких как список постов, комментариев, альбомов, фотографий, задач и пользователей. В этом уроке мы получим список пользователей в наше приложение. Так что посмотрите, каждый объект пользователя имеет кучу свойств, таких как ID, имя, имя пользователя и так далее. Так что вернемся к нашему проекту. Давайте перейдем в папку app, затем откроем папку users, а затем перейдем к этой странице. Теперь это серверный компонент, и в серверных компонентах мы можем использовать функцию fetch, с которой вы, вероятно, знакомы. Эта функция определена в браузерах, и с ее помощью мы можем отправлять HTTP-запросы на бэкенд. Так что здесь мы передаем URL нашей конечной точки, который мы берем отсюда. Скопируйте и вставьте его. Теперь это возвращает Promise, так что нам придется подождать, чтобы получить ответ. Теперь, поскольку мы используем await здесь, нам придется сделать этот компонент асинхронным. Теперь в этом красота этого подхода. С этим подходом нам не нужно использовать переменную состояния, нам не нужно использовать хук эффекта с нулевой зависимостью. Нет никакой церемонии, мы просто вызываем fetch, чтобы получить данные, и все это происходит на сервере. Вы увидите это через минуту. Так что мы получаем ответ, затем вызываем response.json. Это также возвращает Promise, так что мы подождем, чтобы получить данные. В данном случае наши пользователи. Далее мы сопоставляем этих пользователей с кучей элементов списка, точно так же, как мы рендерим их в приложении React. Так что для нашей разметки давайте заменим этот div на фрагмент. Здесь мы добавляем H1 с названием "Users". Затем мы добавляем неупорядоченный список, и здесь мы сопоставляем этих пользователей. Мы берем каждого пользователя. Теперь, если вы наберете user., посмотрите, мы ничего не видим, потому что компилятор не знает о типе этих объектов пользователей. Так что, если вы наведете мышь на эту константу, посмотрите, тип этой константы — any, что означает, что мы не знаем, это может быть что угодно. Вот где мы можем использовать некоторую магию TypeScript для улучшения нашего кода. Так что вне этого компонента мы определяем интерфейс или тип под названием user, и здесь мы говорим, что каждый пользователь имеет свойство ID типа number. Он также имеет name типа string и так далее. Мы могли бы перечислить все свойства, которые у нас есть здесь, но это не обязательно для этого урока. Так что мы будем держать вещи простыми. Так что с этим интерфейсом мы определяем форму наших объектов пользователей. Хорошо, теперь там, где мы объявляем эту константу, мы аннотируем ее ее типом, который является массивом user. Хорошо, с этим, когда мы набираем user., мы можем видеть свойства объектов пользователей. Так что это преимущество использования TypeScript. С TypeScript мы получаем все автодополнение, когда мы кодируем, а также, если у нас есть какие-либо ошибки, такие как опечатки, мы можем отловить эти ошибки во время сборки, прежде чем мы запустим и развернем наше приложение. Хорошо, так что здесь мы будем сопоставлять каждого пользователя с элементом списка. Сначала мы даем ему ключ, который мы устанавливаем на user.id, и здесь мы рендерим user.name. Это все, что нам нужно было сделать. Так что наш код проще, здесь нет хуков состояния и эффекта. Наш пакет будет меньше, потому что этот компонент будет на сервере. Теперь вернемся в браузер. Давайте перейдем на страницу пользователей. Вот наши пользователи. Красиво. Теперь давайте откроем вкладку Network и обновим страницу. Так что посмотрите на документ, который мы получили с бэкенда. Так что все наши пользователи рендерятся прямо здесь. Это потому, что рендеринг происходит на сервере. В отличие от этого, в типичных приложениях React или везде, где мы используем клиентский рендеринг, браузер изначально получает пустой документ, затем он вызывает бэкенд для получения данных, а затем рендерит контент. Так что всегда есть дополнительный круговой путь к бэкенду, и наше приложение не дружественно к поисковым системам. Так что, чтобы получать данные, когда это возможно, мы должны получать их в серверных компонентах. [Музыка] Получение данных в серверных компонентах имеет дополнительное преимущество, и это кэширование. Что такое кэширование? Ну, идея кэширования заключается в том, чтобы хранить данные где-то, откуда их быстрее получить. В основном есть три места, откуда мы можем получить данные: мы можем получить их из памяти, из файловой системы или из сети. Теперь, когда мы спускаемся по этому списку, получение данных становится медленнее. Например, получение данных из сети всегда медленнее, чем получение их из файловой системы. По этой причине Next.js поставляется со встроенным кэшем данных. Так что всякий раз, когда мы используем функцию fetch для получения некоторых данных, Next.js автоматически сохранит результат в своем кэше данных, который основан на файловой системе. Так что в следующий раз, когда нам понадобятся те же данные, в следующий раз, когда мы обратимся к тому же URL, Next.js не будет обращаться к JsonPlaceholder, он получит данные из своего кэша данных, из файловой системы. Конечно, у нас есть полный контроль над этим поведением кэширования. Если у вас есть данные, которые часто меняются, мы можем отключить кэширование или рассматривать данные в кэше как свежие в течение определенного периода времени. Позвольте мне показать вам. Так что здесь, когда мы вызываем функцию fetch, мы можем передать второй аргумент, который является объектом опций. Позвольте мне поставить это на новую строку, чтобы мы могли четко видеть. В этом объекте мы можем установить cache в no-store, чтобы отключить кэширование. Это один вариант, и это полезно, если у вас есть данные, которые часто меняются. В тех ситуациях мы всегда хотим показывать свежие данные нашим пользователям, верно? Другой вариант — сохранять данные свежими в течение определенного периода времени. Для этого, вместо отправки cache в no-store, мы устанавливаем next в объект. В этом объекте мы можем указать параметры конфигурации, специфичные для Next.js. Так что здесь мы можем установить revalidate в значение, например, 10, и это означает, что Next.js будет запускать фоновую задачу и получать свежие данные с бэкенда каждые 10 секунд. Так работает кэширование в Next.js. Теперь одна вещь, которую вам нужно знать, это то, что это поведение кэширования реализовано только в функции fetch. Так что, если вы используете стороннюю библиотеку, такую как Axios, вы не получите этого, вы не получите кэш данных. [Музыка] В Next.js у нас есть еще один метод оптимизации производительности, называемый статическим рендерингом или генерацией статических сайтов. Идея статического рендеринга заключается в том, что если у вас есть страницы или компоненты со статическими данными, мы можем заставить Next.js рендерить их один раз, когда мы собираем наше приложение для продакшена. Так что в следующий раз, когда эти страницы или компоненты понадобятся, Next.js не будет их перерендеривать. Он получит их полезную нагрузку или контент из своего кэша, который основан на файловой системе. Это статический рендеринг, то есть рендеринг во время сборки. В сравнении у нас есть динамический рендеринг, который происходит во время запроса. Давайте посмотрим на это в действии. Так что вернемся к нашей странице пользователей. Давайте добавим временную метку над списком пользователей. Так что здесь мы добавляем параграф и рендерим. Сначала мы создаем новый объект даты, а затем вызываем toLocaleTimeString. С этим мы можем увидеть, когда эта страница была отрендерена. Теперь вернемся в браузер. Давайте обновим несколько раз. Так что посмотрите, временная метка меняется. Это происходит только в режиме разработки. Но если вы соберете это приложение для продакшена, вы увидите, что временная метка не изменится, потому что Next.js будет рассматривать эту страницу как статическую страницу. И вот причина. Ранее я говорил вам, что по умолчанию всякий раз, когда мы используем функцию fetch, Next.js будет кэшировать данные. Так что он рассматривает наши данные как статические или неизменяемые данные. Так что при рендеринге этой страницы Next.js видит, что эта страница имеет статические данные, поэтому он решает рендерить эту страницу статически во время сборки. Но если мы отключим кэширование, Next.js думает, что данные на этой странице изменятся, поэтому он не будет рендерить эту страницу статически, он будет рендерить ее во время запроса. Чтобы увидеть это в действии, давайте вернемся в окно терминала. Остановите этот процесс. Теперь ранее мы использовали npm run dev для запуска этого приложения на нашем сервере разработки. Теперь, чтобы собрать это для продакшена, мы выполняем npm run build. Хорошо, здесь вы можете увидеть все маршруты, которые генерируются при сборке нашего приложения для продакшена. Так что это наш корневой маршрут или главная страница. У нас есть маршрут для нашего favicon, у нас есть один для страницы пользователей, другой для страницы users/new и так далее. Теперь посмотрите на значок перед каждым из этих маршрутов. Здесь мы видим только круги. Теперь здесь внизу вы можете увидеть, что круг означает статичный. Так что эти страницы автоматически рендерятся как статический HTML. Теперь, если вы запустите это приложение в продакшене, что мы можем сделать, выполнив npm start, а затем вернемся в браузер, давайте обновим. Посмотрите, временная метка не меняется, потому что эта страница была статически отрендерена во время сборки. Теперь вернемся на эту страницу. Давайте отключим кэширование и пересоберем это приложение для продакшена. Так что в качестве второго аргумента мы передаем объект опций, и здесь мы устанавливаем cache в no-store. Хорошо, теперь вернемся в терминал. Остановим этот процесс и пересоберем приложение. Отлично. Теперь посмотрите на значок перед маршрутом users. Вместо круга у нас есть лямбда. И здесь внизу вы можете увидеть, что лямбда означает рендеринг на сервере. Так что серверный рендеринг во время выполнения. Теперь давайте запустим приложение в продакшене. Вернемся в браузер. Давайте обновим. Теперь посмотрите, каждый раз, когда мы обновляем, временная метка меняется. Давайте подведем итог всему, что я узнал о рендеринге в Next.js. Рендеринг может происходить на клиенте или на сервере. Если он происходит на сервере, он может происходить во время сборки, что называется статическим рендерингом, или во время запроса, что называется динамическим рендерингом. Так что это подводит нас к концу этого раздела. В следующем разделе мы поговорим о стилизации приложений Next.js. Так что я увижу вас там. Добро пожаловать обратно на наш курс Next.js. В этом разделе мы изучим различные способы стилизации наших приложений и сделаем их красивыми. Мы рассмотрим глобальные стили, CSS-модули, Tailwind и Daisy UI. Так что давайте приступим и начнем. [Музыка] Ранее в курсе мы кратко говорили о нашем глобальном файле стилей в папке app. Так что давайте откроем globals.css. В этом файле наверху у нас есть три директивы для импорта базовых стилей из Tailwind. Теперь мы поговорим о Tailwind позже в этом разделе, но очень кратко: Tailwind — это очень популярный CSS-фреймворк. Хорошо, после этого у нас есть этот корневой селектор. Здесь мы обычно определяем пользовательские свойства, такие как foreground RGB и так далее. Затем у нас есть media prefers-color-scheme dark. С помощью этой относительно новой функции CSS мы можем определить, находится ли пользователь в темном режиме или нет. Если да, вы можете увидеть, что значение этих пользовательских свойств перезаписывается. Теперь здесь внизу вы можете увидеть, что мы использовали значение этого пользовательского свойства в качестве цвета элемента body. Так что мы не используем background start и end RGB, они использовались ранее, когда у нас был градиент на нашей главной странице. Так что, прежде чем идти дальше, давайте немного приведем в порядок. Я удалю эти две строки и эти две строки отсюда. И также давайте вернемся в терминал и убедимся, что мы запускаем это приложение в режиме разработки. Так что всякий раз, когда мы вносим сюда какие-либо изменения, мы можем видеть изменения немедленно. Так что npm run dev. Хорошо. Вернемся к этому файлу. Так что это наш глобальный файл стилей, и мы должны использовать его для стилей, которые действительно глобальны в нашем приложении. Стили, которые применяются ко всем страницам, такие как все, что связано с элементом body, заголовками, нашими гиперссылками и так далее. Все, что специфично для страницы или компонента, мы должны реализовать где-то еще. Так что одна вещь, которую вы не должны делать здесь, это не определять пользовательские классы, такие как user-list, потому что это применяется только к конкретному компоненту или странице. С этим подходом, по мере того, как мы создаем все больше и больше компонентов, этот глобальный файл стилей становится действительно большим и становится неуправляемым. И что более важно, когда мы изменяем или удаляем наши компоненты, нам придется помнить, чтобы вернуться и сделать некоторую очистку здесь, иначе со временем у нас будет много мертвых стилей в этом файле. Если вы работали с CSS некоторое время, вы знаете, о чем я говорю. Так что зарезервируйте этот файл для стилей, которые действительно глобальны. Для стилей, которые специфичны для страницы или компонента, используйте CSS-модули или Tailwind, о которых мы поговорим дальше. [Музыка] Хорошо, давайте поговорим о CSS-модулях. CSS-модуль — это файл CSS, который ограничен страницей или компонентом. Это способ предотвратить конфликты или перезапись стилей друг другом. Если вы работали с CSS некоторое время, вы знаете, что если у вас один и тот же класс определен в двух разных местах, в двух разных файлах стилей, эти классы могут переопределять друг друга в зависимости от того, как мы импортируем эти файлы стилей. CSS-модули призваны решить эту проблему. Давайте посмотрим, как они работают. Так что здесь, в папке components, у нас есть компонент под названием ProductCard. Теперь, скажем, мы хотим создать некоторые стили для этого компонента. Так что здесь мы добавляем новый файл. Мы можем назвать этот файл как угодно, но лучше назвать его так же, как и компонент. Так что ProductCard. Важно, чтобы расширение было .module.css. Хорошо? Теперь в этом файле или в этом CSS-модуле мы можем определять классы, которые ограничены нашим компонентом ProductCard. Так что давайте определим класс под названием card. И, конечно, мы можем определить этот класс где-то еще, не беспокоясь о том, что эти классы будут конфликтовать. Хорошо, так что здесь мы можем применить отступ в один rem и границу в один пиксель, solid CCC. Теперь мы возвращаемся к нашему компоненту и импортируем этот файл стилей. Так что мы набираем import styles from './product-card.module.css'. Имя, которое мы здесь присваиваем, не имеет значения, но обычно мы идем с "styles", и это будет объект JavaScript. Так что классы, которые мы определяем в CSS-модуле, в конечном итоге станут свойствами этого объекта. Так что здесь, если я наберу styles, я должен увидеть эти свойства, но я не знаю, почему IntelliSense сейчас не работает для меня, поэтому я прошу прощения за это. Так что здесь я должен увидеть классы, которые мы определили, такие как card и так далее. И это означает, что в CSS-модулях мы не можем использовать дефисы при именовании этих классов, таких как card-container, потому что это недействительное имя для свойства JavaScript. Так что в этих файлах всегда используйте нотацию camelCase. Так что мы удаляем дефис и делаем первую букву второго слова заглавной. Хорошо, теперь давайте просто упростим вещи. Мы идем с card. Вернемся к нашему компоненту. Так что у нас есть этот объект. Теперь на этом div мы устанавливаем className, чтобы использовать наши фигурные скобки и установить его на styles.card. Теперь вернемся в браузер. Здесь, на главной странице, мы можем видеть стиль, примененный к нашей карте. Но позвольте мне показать вам кое-что интересное. Давайте щелкнем правой кнопкой мыши здесь и проверим это в Chrome DevTools. Вот наш div. Посмотрите на имя класса. Это не тот класс, который мы создали, верно? Это сгенерировано автоматически. Так что происходит здесь? Этот проект использует инструмент под названием PostCSS для преобразования наших имен классов CSS. Так что вернемся к нашему проекту. Здесь, в корневой папке, у нас есть файл под названием postcss.config.js. В этом файле в настоящее время у нас есть два плагина: один — Tailwind, другой — Autoprefixer. Теперь, по большей части, нам не нужно касаться этого конфигурационного файла, но если вы опытный пользователь PostCSS, вы знаете, что здесь вы можете предоставить свою собственную конфигурацию. Так что при сборке нашего приложения Next.js использует PostCSS для преобразования наших имен классов и генерации уникальных имен классов, которые не конфликтуют. Так работают CSS-модули. Теперь последнее, прежде чем мы закончим этот урок. В настоящее время я поместил файл CSS и файл TypeScript рядом друг с другом. Если вам не нравится смешивать ваши файлы CSS и TSX, вы можете сгруппировать их в папки. Так что здесь мы можем создать папку, например, ProductCard. Это контейнер для нашего компонента. В этом компоненте у нас может быть файл TSX и файл CSS. Хорошо, и, конечно, мы можем использовать ту же технику с нашими страницами. Так что мы можем использовать CSS-модули для определения стилей, которые локальны для конкретной страницы. [Музыка] Хорошо, давайте поговорим о Tailwind. Tailwind — это очень популярный CSS-фреймворк, который использует концепцию утилитарных классов. Так что здесь, на tailwindcss.com, вы можете увидеть, что у нас есть куча классов, таких как flex, pt-4, что означает padding-top 4, text-center и так далее. Так что здесь у нас тонна маленьких утилитарных классов, и мы можем комбинировать их для стилизации нашего приложения. Некоторым людям это нравится, некоторым — нет. Я должен признать, что у меня тоже есть отношения любви-ненависти с Tailwind, но я думаю, что я люблю его больше, чем ненавижу. Если вы никогда раньше не использовали его, я настоятельно рекомендую вам попробовать, потому что в наши дни многие проекты построены с использованием Tailwind. Так что, если вы хотите повысить свои навыки и расширить возможности трудоустройства, вам следует иметь Tailwind в своем наборе навыков. Так что в Tailwind у нас есть тонна маленьких утилитарных классов. Например, для управления отступами у нас есть куча классов, которые начинаются с p, за которым следует число, которое может быть 1, 2, 3, 4 и так далее. Чем больше число, тем больше отступ. У нас также есть px для применения горизонтального отступа. Это то же самое, что применять левый и правый отступ. У нас также есть py для вертикального отступа. У нас есть pt для padding-top, pr для padding-right, pb для padding-bottom и pl для padding-left. Теперь вам не нужно запоминать ничего из этого. По мере практики вы быстро освоите их. Теперь для полей у нас есть похожие классы, но они начинаются с m, за которым следует число, mx для горизонтального поля и y для вертикального поля и так далее. Теперь для стилизации текста, опять же, у нас есть тонна классов. Например, для управления размером у нас есть text-xs, что означает extra-small. У нас есть text-small, text-base, что является обычным размером. У нас есть text-large, x-large, 2x-large и так далее. Для применения цветов у нас есть классы, которые начинаются с text, за которым следует цвет. Так что, если вы поищете "Tailwind color palette" в Google, на этой странице вы увидите палитру цветов по умолчанию, которая поставляется с Tailwind. Так что у нас есть все эти красивые цвета, и по большей части нам не нужно их настраивать. Они просто отлично выглядят, как есть. Но вы всегда можете настроить их и использовать цвета, специфичные для вашего бренда. Теперь посмотрите, например, для sky у нас есть различные оттенки синего, которые начинаются с 50 и идут до 950. Чем больше число, тем темнее цвет. Вы увидите пример этого позже в этом видео. Теперь вернемся к нашему слайду. Мы управляем цветом фона. У нас есть куча классов, которые начинаются с bg, за которым следует цветовой код. Теперь для управления толщиной шрифта у нас есть куча классов, таких как font-thin, font-light, normal, medium, bold и так далее. Такова идея Tailwind. Теперь есть гораздо больше классов в Tailwind, которые мы можем охватить здесь, но наш фокус здесь, в этом курсе, на Next.js, а не на Tailwind. Я просто хочу показать вам основы, чтобы вы могли узнать остальное самостоятельно. Так что давайте рассмотрим эти классы в действии, а затем я объясню, почему вы можете захотеть использовать Tailwind. Так что вернемся к нашему проекту. Ранее мы использовали CSS-модуль для стилизации нашего ProductCard. Давайте посмотрим, как мы можем использовать
Вместо CSS-модуля для стилизации этого компонента используется Tailwind, поэтому в этом файле нам не нужно импортировать наш CSS-модуль. Вместо этого мы можем применять классы утилит Tailwind прямо здесь. В этом уроке я собираюсь использовать другой набор стилей, чем те, которые мы применяли в нашем CSS-модуле, чтобы вы могли увидеть больше Tailwind в действии. Итак, мы добавим к этому некоторый отступ. Мы набираем p-тире. Если вы нажмете Ctrl и пробел, вы увидите все классы отступов. У нас есть p-0, что эквивалентно отступу ноль. У нас есть отступ один, что эквивалентно 0,25 RAM или 4 пикселям. И по мере увеличения числа мы получаем больше отступов. Так что этот IntelliSense поставляется с расширением, которое мы установили в начале курса. Итак, давайте добавим к этому отступ пять, вертикальный отступ пять. Теперь я хочу придать ему фоновый цвет. Итак, мы набираем BG-тире. Посмотрите снова в IntelliSense, мы можем увидеть все цвета. Я собираюсь выбрать Sky-400. Теперь, чтобы сделать текст здесь белым, мы применяем text-white. Мы можем сделать его большим. Итак, здесь мы используем text-xl или 2XL, 3XL и так далее. Снова справа вы можете увидеть фактический примененный размер. Итак, для text-xl размер шрифта составляет 1,25 RAM или 20 пикселей. Теперь здесь есть часть, которая становится интересной. Здесь у нас есть псевдоселекторы, такие как hover, и с помощью этого мы можем применять стили, когда мы наводим курсор на эту коробку или этот div. Итак, мы можем изменить фоновый цвет на BG-sky-600 или 500, чтобы сделать его немного темнее. Теперь вернемся в браузер. Вот наш div. Если мы наведем на него курсор, вы увидите, что цвет меняется. Вот так мы стилизуем наши приложения с помощью Tailwind. Теперь преимущество Tailwind в том, что мы можем начать наши компоненты прямо здесь, в нашем файле компонента. Нам не нужно переключаться между файлом CSS и файлом компонента. Все находится в одном месте. Теперь некоторые люди утверждают, что это нарушает принцип разделения ответственности, но я должен с этим не согласиться, потому что вся идея разделения ответственности заключается в организации нашего кода на отдельные разделы или модули, каждый из которых имеет отдельную ответственность. Если вы будете следовать этому принципу, у нас будет больше возможностей для повторного использования. Но в этом случае сам этот компонент React является модулем и определяет границу повторного использования. Так что то, что у нас находится внутри этой границы, является чисто деталью реализации. У нас может быть разметка с JavaScript и стилями, расположенными рядом друг с другом. То, что находится внутри, не имеет значения для внешнего мира, если этот компонент или этот модуль пригоден для повторного использования. Это просто мое мнение. Если вы не согласны или вам не нравится использовать Tailwind, это совершенно нормально. Но опять же, если вы хотите расширить свои возможности трудоустройства, я настоятельно рекомендую вам изучить Tailwind, потому что в наши дни он пользуется большим спросом. Но есть еще одно преимущество использования Tailwind, и это причина, по которой я лично люблю Tailwind. С Tailwind, когда мы создаем наше приложение, наш окончательный CSS-пакет будет содержать только классы утилит, которые мы использовали в нашей разметке. Так что, если завтра мы удалим этот div, ни один из этих классов не будет в нашем окончательном CSS-пакете, если мы не использовали их где-то еще. Так что с Tailwind нам не нужно помнить об очистке, когда мы изменяем или удаляем наши компоненты. С CSS-модулями, если мы удалим этот компонент, нам придется помнить об удалении этого файла CSS. Или, если мы изменим структуру здесь, у нас все еще могут быть неиспользуемые классы в нашем CSS-модуле. Так что нам придется помнить, чтобы вернуться и почистить. Так что это преимущество, которое убедило меня начать использовать Tailwind. Но с другой стороны, мне не нравится, что со временем, по мере усложнения нашей разметки, у нас будет много этих классов, и код читать трудно. Но это просто вопрос привыкания. Это не ужасно плохо, но это то, что отталкивает некоторых людей на ранних этапах. Но со временем, я думаю, преимущества перевешивают недостатки. Хорошо, теперь давайте поговорим о DaisyUI. DaisyUI — это очень популярная библиотека компонентов для Tailwind. Это что-то вроде Bootstrap для Tailwind. Так что, если вы зайдете на daisyui.com, вы увидите все эти компоненты. Например, у нас есть аккордеоны, оповещения, хлебные крошки, кнопки, карточки, карусели, пузыри чата и так далее. Очень, очень полезно. Очень легко использовать. Итак, давайте сначала перейдем на страницу установки. Нам нужно установить Daisy в качестве зависимости для разработки. Итак, я скопирую эту строку. Теперь вернемся в VS Code. Я открыл окно терминала. Вы можете открыть его через Терминал -> Новый терминал. Теперь давайте вставим это. Хорошо. Далее, мы должны добавить Daisy в качестве одного из плагинов Tailwind. Итак, мы должны перейти в файл конфигурации Tailwind в корне нашего проекта. Так что это прямо здесь. В настоящее время плагинов нет. Итак, давайте скопируем эту строку и вставим ее сюда. Это буквально все, что нам нужно сделать. Теперь давайте посмотрим, как мы можем использовать эти компоненты. Итак, в качестве примера мы рассмотрим компонент кнопки. Итак, здесь у нас есть куча классов, таких как BTN, BTN-neutral, BTN-primary, secondary и так далее. Точно так же, как Bootstrap, под капотом эти классы используют Tailwind. Так что вместо того, чтобы вручную комбинировать кучу маленьких классов Tailwind для создания кнопки, мы можем просто использовать кнопку, которая идет с Daisy. И, конечно, мы всегда можем настроить эти кнопки. Хорошо, чтобы создать кнопку, нам нужен пример где-нибудь здесь. Вот он. Это просто базовая кнопка. У нас также есть neutral, primary, secondary и так далее. Итак, вернемся к нашему коду. Давайте стилизуем компонент, который мы создали ранее: "Добавить в корзину". Итак, здесь у нас есть кнопка. Мы устанавливаем имя класса на BTN, BTN-primary. Нам не нужно ничего импортировать в этом файле. Хорошо, теперь вернемся на главную страницу. Вот что мы получаем. Давайте уберем этот синий фон, потому что он выглядит как-то странно. Итак, мы вернемся в product-card.tsx, и я удалю все эти классы Tailwind. Хорошо, вот что у нас осталось. Теперь в Daisy есть концепция тем. Например, если вы посмотрите на эту страницу тем, вы увидите все доступные темы. Теперь в этом уроке я собираюсь использовать тему под названием "winter". И вы всегда можете предварительно просмотреть эти темы. Так что сверху вы можете выбрать их и увидеть, как выглядит ваше приложение. Вот темный режим. Здесь у нас тема "cupcake" и так далее. Теперь, чтобы использовать тему, нам нужно выполнить два шага. Сначала нам нужно перейти в файл конфигурации Tailwind и добавить этот раздел для DaisyUI. Итак, здесь мы активируем темы, которые хотим использовать. Итак, давайте скопируем этот раздел и вернемся в Tailwind-config.ts, сразу после плагинов, вставим это. Итак, у нас есть DaisyUI, у нас есть темы. Я не хочу использовать ни одну из них. Я хочу использовать только тему "winter". Второй шаг — применить эту тему к нашему HTML-элементу. Итак, вернемся к документации. Посмотрите сюда. У нас есть атрибут данных для указания темы. Для этого нам нужно перейти в наш файл макета, потому что именно здесь у нас есть наш HTML-элемент. Итак, мы устанавливаем data-theme на "winter". Теперь вернемся на нашу главную страницу. Наша кнопка выглядит синей. Красиво. Теперь давайте перейдем на страницу пользователей и поместим этих пользователей в таблицу. Итак, давайте перейдем на страницу пользователей и заменим этот неупорядоченный список таблицей. Итак, мы выбираем это и нажимаем Command+D на Mac или Ctrl+D на Windows, чтобы активировать множественные курсоры. Теперь мы можем изменить эти два элемента одновременно. Итак, мы меняем это на таблицу. Затем мы нажимаем Escape, чтобы деактивировать множественные курсоры. Теперь внутри этой таблицы мы хотим иметь t-head. Внутри t-head мы хотим иметь t-r, а внутри t-r мы хотим иметь два элемента t-h. Давайте нажмем Tab. Вот наша разметка. Красиво. Теперь здесь у нас будет два столбца. Первый — имя пользователя, второй — адрес электронной почты пользователя. Теперь после элемента t-head мы должны добавить t-body. Затем мы будем отображать наших пользователей внутри t-body и заменять li на t-r. Итак, еще раз нажимаем Command+D на Mac или Ctrl+D на Windows, чтобы изменить оба этих элемента одновременно. Итак, давайте изменим это на t-r. Внутри t-r мы хотим иметь два элемента t-h. Итак, t-h * 2. Давайте поместим это на отдельную строку. Хорошо. В первом t-h мы хотим отобразить user.name. Во втором мы хотим отобразить user.email. И в настоящее время у нас нет email в интерфейсе, который мы определили для наших пользователей. Вот почему мы получаем ошибку компиляции. Так что это еще одно преимущество использования TypeScript. Компилятор TypeScript сообщает нам об этих проблемах до того, как мы запустим или развернем наше приложение. Мы можем поймать эти ошибки во время компиляции или даже во время кодирования. Итак, выше у нас есть интерфейс пользователя. Давайте добавим свойство email типа string. Теперь ошибка исчезает. Прекрасно. Итак, вернемся в браузер. Вот что мы получаем. Теперь давайте применим пару классов из Daisy, чтобы сделать эту таблицу немного лучше. Итак, вернемся к нашему коду. Вот наша таблица. Мы устанавливаем имя класса на table и table-bordered. И, конечно, вы можете найти это в документации для компонента таблицы в DaisyUI. Хорошо, это намного лучше. Теперь я допустил ошибку ранее при отображении этих строк. Я использовал элемент t-h, поэтому они отображаются как жирные. Но мы должны использовать t-h только как столбец наших таблиц. Итак, давайте изменим все эти элементы t-h на t-d. Еще раз выбираем один из них и нажимаем Command+D, чтобы выбрать больше из них. Итак, теперь у нас четыре курсора. Давайте изменим все их на t-d. Хорошо. Вот что мы получаем. Теперь нам больше не нужна временная метка. Так что давайте уберем ее и отсюда. Хорошо. Итак, на данный момент мы закончили. В следующем разделе мы более подробно поговорим о маршрутизации и навигации. Привет, ребята. Надеюсь, вам понравилось смотреть этот учебник. Я просто хотел упомянуть, что этот учебник — первый час моего полного курса по Next.js. Так что после того, как вы закончите это, если вы хотите узнать больше, я настоятельно рекомендую вам перейти на полный курс, потому что он намного быстрее и проще, чем переключаться между кучей случайных несвязанных учебников здесь на YouTube. Полный курс длится 5 часов и научит вас всему, что вам нужно для создания полнофункциональных приложений с помощью Next.js. Он также поставляется с сертификатом о прохождении и 30-дневной гарантией возврата денег. Так что, если вы не удовлетворены, попросите полный возврат средств. Вы получите все свои деньги обратно без вопросов. Если вы заинтересованы, ссылка находится под этим видео.