4 - Первое React-приложение с помощью Vite

Оценить качество материала и подачу материала автором видео:

Front-end

Трудоустройтесь middle front-end разработчиком на React JS (TypeScript) за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Front-end

Back-end

Трудоустройтесь middle back-end разработчиком за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Back-end

Карьерный бустер

Получите коммерческий опыт на реальных стартапах, прокачайте tech & soft навыки, научитесь работать в команде, проходить собеседования и получите первую работу в IT!

Перейти на курс
Карьерный бустер

Основы Front-end

Сделайте первый шаг в IT, освоив базовые знания разработки и научившись создавать небольшие проекты на JavaScript

Перейти на курс
Основы Front-end

Основы Back-end

Сделайте первый шаг в IT, освоив базовые знания разработки. Без опыта. Без математики. Только практика: JavaScript, SQL, Node JS, база данных

Перейти на курс
Основы Back-end

Vite

Автор конспекта: Арина Василевская

🔗

Полезные ссылки:

Проверка установки Node.js

Для начала проверяем, что Node.js установлен. Для этого в командной строке вводим команду:

Terminal
node -v

📌 На момент написания конспекта актуальная версия v22.11.0. Ваша версия может отличаться.

Установка Vite

Vite — современный и быстрый инструмент сборки. Автоматически настраивает проект и позволяет начать разработку без долгих конфигураций

  1. Переходим на сайт vite.dev → раздел Get Started.
  2. В документации находим секцию Scaffolding Your First Vite Project.
🤓

Scaffolding — это создание базового шаблона проекта со всеми нужными папками, файлами и зависимостями.

  1. У себя на компьютере открываем папку, в которой хотим создать проект.
  2. В этой папке запускаем терминал.
  3. В терминале вводим
Terminal
npm create vite@latest
  • npm — пакетный менеджер, который идёт вместе с Node.js.
  • npm create <name> — это алиас (другое имя) для команды npx create-<name>.
💡

Для того, чтобы быстро посмотреть информацию по командам, можно написать в терминале npm <command> --help. Например, npm create --help.

Здесь вводим y, подтверждаем, что мы хотим установить Vite.

createVite

  1. Вводим имя папки, например:
Terminal
lesson-01

projectName

Название папки:

  • в нижнем регистре (lowerCase)

  • используем латинский алфавит

  • не используем специальные символы

  • не ставим пробелы

  1. Выбираем фреймворк из предложенных, в нашем случае это React.

frameWork

  1. Выбор языка. Выбираем TypeScript, в дальнейших уроках будем разбирать и изучать данный язык.

language

  1. Если все успешно, то видим в терминале:

resultNpm

Открытие проекта в IDE

Откроем проект в WebStorm (или другой IDE). Vite сразу подготовил нам структуру проекта с множеством файлов и папок. Жмем правой кнопкой мыши по папке проекта и выбираем Open folder as WebStorm project.

Package.json

Почему папка считается Node.js-проектом?

Определяющим фактором является наличие файла package.json - основного конфигурационного файла проекта.

Он выполняет несколько функций:

  • хранит информацию о проекте (название, версию, автора и т.д.);
  • фиксирует список зависимостей;
  • задаёт скрипты для сборки, запуска и тестирования;

Если в папке нет package.json, Node.js и npm не воспринимают её как проект.

Dependencies и DevDependencies

Внутри package.json есть две ключевые секции:

  1. Dependencies

Это библиотеки, которые непосредственно попадут в браузер и будут выполняться как часть фронтенд-приложения. В нашем случае:

  • react
  • react-dom

Они нужны для построения интерфейса и работы с DOM, без необходимости вручную управлять низкоуровневым API браузера и непосредственного взаимодействия с DOM-элементами.

  1. DevDependencies

Это пакеты, которые нужны только на этапе разработки:

  • транспиляция (TypeScript → JS)
  • бандлинг (сборка)
  • плагины для Vite
  • ESLint
  • TypeScript и его конфигурации

Именно сюда входит сам Vite и вспомогательные инструменты. Они не попадут в продакшн-сборку, но делают Developer Experience (DX) удобным. На данном этапе не нужно детально разбирать каждый пункт Dependencies.

Как запустить приложение

Так как мы работаем с фронтенд-проектом, то мы не можем запустить его просто напрямую через Node.js, так как:

  • используется TypeScript и JSX/TSX,
  • код нужно транспилировать и собрать в бандл,
  • требуется запустить локальный сервер, который отдаёт результат в браузер. Поэтому для запуска используется не node, а специальный скрипт, который подготовил Vite.

Установка зависимостей

После генерации проекта у нас есть package.json. В нём записаны только названия пакетов и их версии. Чтобы скачать все указанные пакеты из npm-реестра, нужно выполнить:

Terminal
npm install

Что происходит при выполнении этой команды:

  1. npm читает package.json.

  2. Скачивает указанные библиотеки из npm-реестра (центрального хранилища пакетов).

  3. Кладёт их в папку node_modules.

Эта папка может достигать больших размеров (сотни мегабайт, иногда гигабайты), поэтому она не хранится в репозитории и не передается другим разработчикам.❗Её всегда можно восстановить через npm install, так как все нужные пакеты указаны в package.json.

  1. Создаёт файл package-lock.json с точными версиями установленных пакетов, чтобы у всех разработчиков был одинаковый набор зависимостей.
📑

Если в package.json написано "prettier": "^2.6.2", при установке может быть выбрана версия 2.7.0, если она уже вышла. Но если версия 2.6.2 зафиксирована в package-lock.json, npm установит именно её, даже если есть новая минорная версия.

📌

Установка зависимостей нужна для того, чтобы превратить описание проекта в реальный работающий набор библиотек и инструментов.

Запуск проекта

Vite для нас уже автоматически прописал в package.json удобный скрипт:

Terminal
npm run dev

Этот скрипт находится в package.json в scripts

scripts

Vite поднимет локальный сервер и выведет в терминал ссылку, например:

Terminal
http://localhost:5173/

Перейдя по ней в браузере, вы увидите пример React-приложения со счётчиком. Кнопка работает: при клике число увеличивается 🚀

reactApp

Структура проекта

Основные папки

  • .idea/: Вспомогательные файлы IDE (WebStorm). Они не влияют на работу проекта. Может называться по-другому, в зависимости от IDE (например, .vscode/ или .cursor/)

  • node_modules/: Содержит все установленные пакеты. Пока это всё, что нам нужно знать.

  • public/: Папка для статических файлов (картинок, шрифтов и т.п.). Например, здесь лежит фавиконка (favicon), которая отображается во вкладке браузера.

  • src/: Главная папка для разработчика. Здесь хранится исходный код: компоненты React, стили и всё, что мы пишем сами.

Главный HTML-файл

В корне проекта находится index.html. Он почти пустой:

  • содержит тег <div id="root"></div> — это «контейнер», в который React будет «монтировать» приложение,
  • подключает src/main.tsx как точку входа.
index.html
<body>
  <div id="root"></div>
  <script type="module" src="/src/main.tsx"></script>
</body>

Точка входа: main.tsx

Здесь начинает оживать наше React-приложение.

main.tsx
import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import "./index.css"
import App from "./App.tsx"
 
createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
  1. Импорты. После установки библиотек их нужно импортировать, чтобы использовать в коде. Также импорты связывают текущий файл с другими файлами проекта.
  • Если путь не начинается с ./ или ../ **(например, createRoot) - импорт идёт из установленных пакетов в node_modules.
  • Если путь начинается с ./ или ../ (например App или ../utils/helpers) - импорт идёт из файла текущей или соседней папки проекта.
  • Импорт JavaScript/TypeScript-файлов (.js, .ts, .tsx) позволяет использовать экспортированные функции, объекты или компоненты.
  • Импорт CSS-файлов (.css) сообщает Vite, что стили из этого файла нужно подключить к странице.
  1. Далее мы видим вызов функции createRoot из React. Она находит в файле index.html элемент с id="root" и использует его как контейнер для всего приложения. После этого приложение монтируется внутрь этого элемента.

  2. StrictMode - специальная обёртка React, которая помогает выявлять потенциальные ошибки и предупреждения на этапе разработки. Она не влияет на поведение приложения в продакшене.

  3. <App/> - компонент, с которого начинается приложение. Сейчас можно воспринимать его как пользовательский тег, созданный разработчиком. На самом деле это вызов компонента App, определённого в файле App.tsx. Компонент возвращает JSX-разметку, которая затем преобразуется React-ом в реальные HTML-элементы.

Разобьем по пунктам. StrictMode пока уберем:

main.tsx
const rootEl = document.getElementById("root")
const reactRoot = createRoot(rootEl!) // 💡 '!' - говорит TypeScript: "этот элемент точно существует".
reactRoot.render(<App />) // React "оживляет" HTML и вставляет разметку в root.

JSX — HTML внутри JavaScript

В React мы можем писать HTML-подобный синтаксис прямо в JS/TS:

tsx
reactRoot.render(<button>Hello</button>)

Это называется JSX - специальный синтаксис, который позволяет писать разметку прямо внутри JavaScript-кода. При компиляции JSX превращается в вызовы функций JavaScript. Браузер не понимает JSX напрямую, поэтому перед выполнением сборщик (например, Vite с Babel) преобразует его в обычный JavaScript — в вызовы функций React.createElement(). Уже этот скомпилированный код выполняется в браузере.

Файлы, содержащие JSX-разметку имеют расширение .jsx, если код написан с использованием typescript, то расширение соответственно - .tsx

Теги, которые используются в JSX, можно разделить на две категории:

  • Стандартные теги (div, button, h1 и т. д.) пишутся с маленькой буквы. На их основе React создаёт DOM-элементы.
  • Компоненты React пишутся с большой буквы (например, App). Они могут содержать стандартные теги, другие компоненты и логику.
tsx
<App />   // компонент
<input/>    // обычный HTML-тег

Дадим определение компонента (оно неполное, в дальнейшем мы его уточним):

💡

Компонент - это функция, которая возвращает JSX-разметку. Пишутся с большой буквы. Могут содержать стандартные элементы, которые затем преобразуются в HTML-теги, а также другие компоненты.

React-компонент должен вернуть один корневой элемент. Если нужно вернуть несколько элементов, то оборачиваем их фрагментом (пустым тегом, <>... </>).

💡

<>...</> или <React.Fragment>...</React.Fragment> (фрагмент) - нужен для того, чтобы объединить несколько тегов вместе, без необходимости создавать вокруг них настоящий HTML-элемент, например, div.

Уберем из App все лишнее. Наш код после рефакторинга:

App.tsx
function App() {
  return (
    //круглые скобочки ставим для того, чтобы красиво выровнять код
    <></>
  )
}
 
export default App

Плеер React

Копия предыдущего index.html

Попробуем реализовать наш плеер с помощью React. Вставим в App.tsx нашу разметку из index.html(из первого урока)

App.tsx
function App() {
  return (
    <>
      <h1>Musicfun player</h1>
      <ul>
        <li>
          <div>Musicfun soundtrack</div>
          <audio
            controls
            src="https://musicfun.it-incubator.app/api/samurai-way-soundtrack.mp3"
          ></audio>
        </li>
        <li>
          <div>Musicfun soundtrack instrumental</div>
          <audio
            controls
            src="https://musicfun.it-incubator.app/api/samurai-way-soundtrack-instrumental.mp3"
          ></audio>
        </li>
      </ul>
    </>
  )
}
 
export default App

Результат в браузере:

PlayerInBrowser

Треки отображаются, и можно нажать Play — они начинают играть. На первый взгляд кажется, что мы откатились назад: будто вернулись к статической верстке и снова создаём элементы вручную в HTML.

На самом деле это не так. То, что выглядит как HTML в React, на самом деле является инструкциями JavaScript — указанием для React, какие элементы создавать и как обновлять их на странице. React берёт эти инструкции и эффективно управляет DOM, обновляя интерфейс без полной перезагрузки страницы.

❗Однако одну из ключевых концепций мы все же нарушили: данные должны быть отделены от алгоритма рендеринга. Давайте вернём это разделение, чтобы компонент стал гибким и легко управляемым.

Вставим над return наш массив треков:

App.tsx
function App() {
  const tracks = [
    {
      title: "Musicfun soundtrack",
      url: "https://musicfun.it-incubator.app/api/samurai-way-soundtrack.mp3",
    },
    {
      title: "Musicfun soundtrack instrumental",
      url: " https://musicfun.it-incubator.app/api/samurai-way-soundtrack-instrumental.mp3",
    },
    {
      title: "Musicfun soundtrack instrumental",
      url: " https://musicfun.it-incubator.app/api/samurai-way-soundtrack-instrumental.mp3",
    },
    {
      title: "Musicfun soundtrack instrumental",
      url: " https://musicfun.it-incubator.app/api/samurai-way-soundtrack-instrumental.mp3",
    },
  ]
 
  return
  //...
}
 
export default App

Создание универсального алгоритма

Далее используем данные из массива для отображения элементов списка.

Важно понимать, что разметка в JSX выглядит как HTML, но на самом деле это особый синтаксис JavaScript. Текст, написанный внутри JSX-тегов, воспринимается как обычная строка. Если же нужно вставить в разметку значение из кода — выражение, переменную или результат функции — используются фигурные скобки {}. Это называется JSX-выражение (JSX expression).

App.tsx
return (
  <>
    <h1>Musicfun player</h1>
    <ul>
      <li>
        <div>{tracks[0].title}</div>
        <audio controls src={tracks[0].url}></audio>
      </li>
      <li>
        <div>{tracks[1].title}</div>
        <audio controls src={tracks[1].url}></audio>
      </li>
    </ul>
  </>
)
💡

Каждый раз, когда мы возвращаемся в браузер, наши изменения уже отобразились. Это происходит благодаря hot reloading, который использует Vite. В отличие от обычной перезагрузки страницы, когда всё приложение полностью обновляется и “умирает”, hot reloading подменяет только изменённые файлы.

Выносим <li> в переменную

Теги (реакт-элементы) являются объектами в момент выполнения программы, поэтому мы можем сослаться на них в переменной.

App.tsx
//...
const li1 = (
  <li>
    <div>{tracks[0].title}</div>
    <audio controls src={tracks[0].url}></audio>
  </li>
)
 
const li2 = (
  <li>
    <div>{tracks[1].title}</div>
    <audio controls src={tracks[1].url}></audio>
  </li>
)
 
return (
  <>
    <h1>Musicfun player</h1>
    <ul>
      {li1}
      {li2}
    </ul>
  </>
)
//...

Также из этих объектов мы можем создать массив. React автоматически пробежит по каждому элементу массива и отрисует его:

App.tsx
//...
const liReactElements = [
  <li>
    <div>{tracks[0].title}</div>
    <audio controls src={tracks[0].url}></audio>
  </li>,
  <li>
    <div>{tracks[1].title}</div>
    <audio controls src={tracks[1].url}></audio>
  </li>,
]
 
return (
  <>
    <h1>Musicfun player</h1>
    <ul>{liReactElements}</ul>
  </>
)
//...

Итак, мы немного улучшили наш код, но текущий наш подход не является универсальным, так как мы привязаны к индексу элемента в массиве данных. Наша конечная цель — получить массив React-элементов динамически, пробежавшись по исходному массиву данных. Когда нужно создать новый массив объектов на основе существующего массива, в JavaScript используется метод массива map.

🔗

Подробнее о методе массива map

Получаем из массива tracks массив newLiReactElements

App.tsx
//...
const newLiReactElements = tracks.map((track) => (
  <li>
    <div>{track.title}</div>
    <audio controls src={track.url}></audio>
  </li>
))
 
return (
  <>
    <h1>Musicfun player</h1>
    <ul>{newLiReactElements}</ul>
  </>
)
//...
📌

Важно помнить: в отличие от forEach, который ничего не возвращает, метод map создаёт новый массив, содержащий столько же элементов, сколько и исходный. Таким образом, мы получили универсальный алгоритм отрисовки: если добавить новые треки в массив данных, они автоматически появятся в браузере, без необходимости вручную менять разметку.

Итог

  • На практике React-разработчики чаще вставляют сам вызов map прямо в JSX — например, внутрь <ul> в фигурных скобках. Результатом работы map будет новый массив React-элементов, и React автоматически отрисует каждый элемент этого массива.

  • Для правильной работы React требует специальный атрибут key для каждого элемента списка. Он позволяет React правильно отслеживать элементы при обновлениях. В HTML это выглядит как обычный атрибут, в React это называется props. Для key обычно используют уникальный идентификатор сущности, например id трека. Добавив этот key, мы устраняем предупреждение и делаем наш код правильным — готовым к использованию в реальных проектах.

App.tsx
function App() {
  const tracks = [
    {
      id: 1,
      title: "Musicfun soundtrack",
      url: "https://musicfun.it-incubator.app/api/samurai-way-soundtrack.mp3",
    },
    {
      id: 2,
      title: "Musicfun soundtrack instrumental",
      url: " https://musicfun.it-incubator.app/api/samurai-way-soundtrack-instrumental.mp3",
    },
    {
      id: 3,
      title: "Musicfun soundtrack instrumental",
      url: " https://musicfun.it-incubator.app/api/samurai-way-soundtrack-instrumental.mp3",
    },
    {
      id: 4,
      title: "Musicfun soundtrack instrumental",
      url: " https://musicfun.it-incubator.app/api/samurai-way-soundtrack-instrumental.mp3",
    },
  ]
 
  return (
    <>
      <h1>Musicfun player</h1>
      <ul>
        {tracks.map((track) => (
          <li key={track.id}>
            <div>{track.title}</div>
            <audio controls src={track.url}></audio>
          </li>
        ))}
      </ul>
    </>
  )
}
 
export default App

🏠Домашнее задание

Создание React приложения со списком дел

  • Цель задания

Создать React приложение с использованием Vite и отрисовать интерактивный список дел, применив знания о компонентах, JSX и методе map.

  • Задача

На основе изученного примера с музыкальным плеером создать React приложение со списком задач, где каждая задача имеет название и статус выполнения.

Требования

  1. Создать новое React приложение на Vite
  2. Установить зависимости
  3. Запустить приложение. После выполнения команды откройте браузер и перейдите по адресу, который покажет в терминале (обычно http://localhost:5173).

Отрисовать список задач используя React и map

Пример данных

ts
const tasks = [
  { id: 1, title: "Купить продукты на неделю", isDone: false },
  { id: 2, title: "Полить цветы", isDone: true },
  { id: 3, title: "Сходить на тренировку", isDone: false },
]

JSX структура

Создайте следующую структуру в return компонента:

  1. Заголовок - элемент h1 с текстом "Список дел"
  2. Список задач - элемент ul со списком всех задач
  3. Каждая задача должна быть элементом li, содержащим:
  • div с названием задачи
  • input типа checkbox для отображения статуса выполнения

Технические детали

❗Обязательные требования:

  • Используйте метод .map() для отрисовки списка задач
  • Не забудьте про атрибут key - используйте task.id
  • Устанавливайте тип чекбокса: type="checkbox"

Ожидаемый результат

lesson2-result

Что делать если что-то пошло не так

Ошибка при создании проекта

  • Убедитесь, что Node.js установлен (выполните node --version)
  • Проверьте подключение к интернету
  • Попробуйте использовать npx вместо npm: npx create-vite@latest

Ошибки в коде

  • Проверьте закрытие всех тегов в JSX
  • Убедитесь, что используете className вместо class
  • Проверьте, что у каждого <li> есть уникальный key

Приложение не запускается

  • Убедитесь, что находитесь в правильной папке проекта
  • Выполните npm install еще раз
  • Перезапустите команду npm run dev
🔗

Если в процессе прохождения домашнего задания возникнут сложности переходи в комнату help2debug, где вы сможете получить поддержку со стороны других участников сообщества

Дополнительно (необязательно)

  • Добавьте больше задач в массив
  • Попробуйте добавить простые стили через CSS
  • Изучите структуру созданного Vite проекта

Боевой маршрут (React Путь Самурая: без альтернатив)

Видеоурок - 5 видео из 30