Как React обрабатывает импорт файлов

React не работает напрямую с файлами — он делегирует эту задачу сборщику (Webpack или Vite). Когда вы пишете import logo from './assets/logo.png', сборщик копирует файл в папку сборки (dist/ или build/), переименовывает его, добавляя хеш для кэширования (например, logo.abcd1234.png), и возвращает в переменную logo строку с новым путём, например /static/media/logo.abcd1234.png. Этот путь — уже не относительная ссылка, а абсолютный URL к скомпилированному ресурсу. Именно поэтому использование строк напрямую в атрибутах, как <img src="./assets/logo.png" />, приводит к проблемам: сборщик не распознаёт такие ссылки как зависимости, не включает файл в бандл, и в продакшене изображение просто не загружается.

Почему файлы «исчезают» — и как этого избежать

В режиме разработки многие файлы по относительным путям могут отображаться корректно благодаря встроенному серверу сборщика (Vite или Webpack Dev Server), который динамически разрешает статические ресурсы. Однако при сборке приложения (npm run build) сборщик включает в бандл только те файлы, которые явно импортированы в коде. Если вы используете строку напрямую в атрибуте, например <img src="./logo.png" />, сборщик не распознаёт эту ссылку как зависимость и не копирует файл в папку сборки. В результате в продакшене изображение не загружается — оно «исчезает».

Как избежать проблемы

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

import logo from './assets/logo.png';
// ...
<img src={logo} alt="Логотип" />

Такой подход гарантирует, что сборщик:

  • увидит зависимость,
  • скопирует файл в папку сборки,
  • переименует его (обычно с хешем для кэширования),
  • подставит корректный путь в переменную logo.

Это не только предотвращает «исчезновение» файлов, но и обеспечивает контроль над используемыми ресурсами: неиспользуемые файлы не попадут в финальную сборку, что уменьшает её размер.

Для чего нужен хеш?

Хеш в имени файла (например, logo.abcd1234.png) решает проблему кэширования в браузере. Когда файл попадает на сервер, браузер может сохранить его локально, чтобы не загружать повторно при следующем посещении. Если имя файла не меняется, браузер продолжит использовать старую версию даже после обновления контента на сервере.

Сборщик генерирует хеш на основе содержимого файла: при любом изменении (даже одного пикселя) хеш меняется, и имя файла становится новым. Это заставляет браузер загрузить обновлённую версию, потому что путь теперь другой. Таким образом, хеширование обеспечивает:

  • долгосрочное кэширование (браузер кэширует файлы на годы, если имя не меняется),
  • мгновенное обновление при изменении контента (новое имя → новая загрузка).