Как импортировать картинки в react
Перейти к содержимому

Как импортировать картинки в react

  • автор:

Компонент Image и оптимизация изображений¶

Компонент Image , импортируемый из next/image , является расширением HTML-тега img , предназначенным для современного веба. Он включает несколько встроенных оптимизаций, позволяющих добиться хороших показателей Core Web Vitals. Эти оптимизации включают в себя следующее:

  • улучшение производительности
  • обеспечение визуальной стабильности
  • ускорение загрузки страницы
  • обеспечение гибкости (масштабируемости) изображений

Пример использования локального изображения:

 1 2 3 4 5 6 7 8 9 10 11
import Image from 'next/image'; import imgSrc from '../public/some-image.png'; export default function Home()  return ( <> h1>Главная страница/h1> Image src=imgSrc> alt="" role="presentation" /> /> ); > 

Пример использования удаленного изображения:

Обратите внимание на необходимость установки ширины и высоты изображения

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import Image from 'next/image'; export default function Home()  return ( <> h1>Главная страница/h1> Image src="/some-image.png" alt="" role="presentation" width=500> height=500> /> /h1> ); > 

Определение размеров изображения¶

Image ожидает получение ширины и высоты изображения:

  • в случае статического импорта (локальное изображение) ширина и высота вычисляются автоматически
  • ширина и высота могут указываться с помощью соответствующих пропов
  • если размеры изображения неизвестны, можно использовать проп layout со значением fill

Существует 3 способа решения проблемы неизвестных размеров изображения:

  • использование режима макетирования fill : этот режим позволяет управлять размерами изображения с помощью родительского элемента. В этом случае размеры родительского элемента определяются с помощью CSS, а размеры изображения с помощью свойств object-fit и object-position :
  • нормализация изображений: если источник изображений находится под нашим контролем, мы можем добавить изменение размеров изображения при его возвращении в ответ на запрос
  • модификация вызовов к API: в ответ на запрос может включаться не только само изображение, но и его размеры

Правила стилизации изображений:

  • выбирайте правильный режим макетирования
  • используйте className — он устанавливается соответствующему элементу img . Обратите внимание: проп style не передается
  • при использовании layout=»fill» родительский элемент должен иметь position: relative
  • при использовании layout=»responsive» родительский элемент должен иметь display: block

Куда поместить картинки в приложении реакт и как к ним достучаться?

Положил в папку public, где лежат index.html и favicon.ico, но как мне теперь достучаться до этой картинки из компонента через тег src?

  • Вопрос задан более трёх лет назад
  • 6969 просмотров

Комментировать
Решения вопроса 1

Mesuti

Если собираете на Webpack, и картинка в src/img/image.svg
А выходная папка dist/

webpack.config в modules

 < test: /\.(png|svg|jpg|gif)$/, use: [< loader: 'file-loader', options: < name: f =>< let dirNameInsideAssets = path.relative(path.join(__dirname, 'src'), path.dirname(f)); return `$/[name].[ext]`; > > >], >,

index.js
import «./img/image.svg»;

В верстке

Ответ написан более трёх лет назад
Нравится 1 1 комментарий
AmirAsanov @AmirAsanov
с svg также работает?
Ответы на вопрос 1

Кладите картинки либо в src и импортируйте их через import.

Либо в паблик и обращайтесь напрямую, но без public. То есть, если картинка лежит в /public/images/cat.jpg, то обращаться к ней нужно через /images/cat.jpg

Путь к изображению в React.js?

Вроде бы как путь к атрибуту src должен быть основан на файловой архитектуре.
Чтобы не зависеть от маршрута, пытаюсь добраться к изображению через абсолютную ссылку.
В итоге по адресу `localhost:3000/components/Users/img/johnson.jpg` я получаю 404.
Почему так получается в React?

let < userName >= useParams(); /* . */ /components/Users/img/$.jpg`> />
  • Вопрос задан более двух лет назад
  • 8074 просмотра

Комментировать
Решения вопроса 1

verkhoturov

Иван В @verkhoturov
HTML-Верстальщик / Frontend Developer

Если картина лежит в «/components/Users/img/johnson.jpg» и вы хотите прописать к ней путь в компоненте Users, то напишите так

import johnsonImg from "./img/johnson.jpg" . />

P.S. Нельзя заглянуть в содержимое src просто указав ссылку типа localhost:3000/src/components/foo/bar/example.file
Если нужны файлы с доступом по прямой ссылке, кладите их в папку «public».

Ответ написан более двух лет назад
Нравится 2 13 комментариев

Vextor-ltd

Влад @Vextor-ltd Автор вопроса
Мда, React точно не для людей делали ))

Vextor-ltd

Влад @Vextor-ltd Автор вопроса

Иван В, поместил изображение в папку с компонентом, делаю импорт и получаю ошибку:

Failed to compile. ./src/components/UserId/UserId.js Module not found: Can't resolve './img/johnson.jpg' in 'C:\OSPanel\domains\react-new-level\unit-03\src\components\UserId'

verkhoturov

Иван В @verkhoturov

поместил изображение в папку с компонентом

файл лежит в ./components/UserId/img/johnson.jpg или ./components/UserId/johnson.jpg ?

Vextor-ltd

Влад @Vextor-ltd Автор вопроса
Он лежит в ‘C:\OSPanel\domains\react-new-level\unit-03\src\components\UserId\img\johnson.jpg’

Vextor-ltd

Влад @Vextor-ltd Автор вопроса

Сорри. Ввёл в заблуждение! Я неправильно назвал картинку. Всё получилось.
Я только начал изучать React. Вообще пока не понимаю что нужно класть в папку ./public
В Gulp и Webpack всегда одна папка для разработки, другая на продакшене у меня была. Всё было просто. Тут пока не въезжаю.

verkhoturov

Иван В @verkhoturov

Влад,
ну как минимум в public лежит index.html — входная точка твоего приложения.
В нее можно класть все файлы, которые нужны в работе приложения, но не используются в компонентах. Например, фавиконы, картинки для превью в соц сетях.

Vextor-ltd

Влад @Vextor-ltd Автор вопроса

Иван В, Всё что я пытаюсь сделать, это передать в роуте в качестве параметра имя картинки и вывести её на экран вот таким вот образом:

import < useRouteMatch, Link, useParams >from 'react-router-dom'; function UserId() < let < userName >= useParams(); let userNameСap = userName[0].toUpperCase() + userName.substring(1); let match = useRouteMatch(); let usersLink = match.url.split('/')[1]; let userNameImg = './img/' + useParams().userName +'.jpg'; // ИМПОРТ В КОМПОНЕНТЕ НЕ ДЕЛАЕТСЯ! КАК БЫТЬ. return ( <> 
User: alt=< userNameСap >/> ` >>Назад
); > export default UserId;

Пока не получается. Мне кажется это каким-то геморроем на пустом месте. На чистом JS или PHP через $_GET[‘imgname’] эта задача решается в считанные секунды!
Я правда 2-й день только React изучаю :))

verkhoturov

Иван В @verkhoturov

Влад, попробуй сделать проще
используй usehistory
с помощью этого хука получаешь доступ к history
а у него используешь метод goBack()

import < useHistory >from "react-router-dom"; const history = useHistory() return (  );

Vextor-ltd

Влад @Vextor-ltd Автор вопроса

Иван В, а что касается изображений? Поместить их в public?

Ладно, пойду читать что-то типа структурирования React-приложений.

verkhoturov

Иван В @verkhoturov

Влад, я на работе делаю так —
если изображение используется в разных компонентах, то в src создаю папку assets и в нее закидываю картинки.
если изображение используется в одном компоненте, то храню ее в папке с компонентом.

Vextor-ltd

Влад @Vextor-ltd Автор вопроса

Иван В, так а как добраться до изображения, если ссылка на него передаётся как параметр в роуте? Ведь в функции компонента импорт делать нельзя.

verkhoturov

Иван В @verkhoturov

Влад, тут пара способов
1) тупо все закинуть в public
2) в компоненте сделать импорт всех картинок и написать функцию, которая получает имя и возвращает нужную картинку, что-то типа такого

import fooImg from "./img/foo.jpg" import barImg from "./img/bar.jpg" const getImg = (name) => < switch (name) < case "foo": return fooImg; case "bar": return barImg; . >>

Как хранить изображения в react-native и есть ли разница?

Пост ориентирован на участников чата и мою команду, поэтому для удобства буду прикреплять ссылки на ключевые сообщения.

Решил вспомнить свой вопрос годичной давности: Есть ли выигрыш в производительности в релизной сборке, если изображения не импортировать в javascript коде, а класть в нативные ресурсы. Начало обсуждения в чате.

Ниже приведен список вариантов использования изображений в react-native:

< uri: 'http://some.url.jpg' >
require('./ic.jpg') // импортирование в javascriot
< uri: 'some_native_asset' >// для изображений из drawable/Images.xcassets
< uri: 'asset:/some_native_asset.jpg' >// для изображений из assets (только андроид)

То есть для отображения локальных картинок, можно использовать один из трех вариантов.

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

1. Возьмите приложение созданное через react-native init (в нем будет меньше кода, но можете и своё взять).

2. Если только что созданное приложение, положите туда в папку картинку (или три штуки, как я): idea.png, idea@2x.png и idea@3x.png и вставьте компонент с картинкой, я в App.js вставил:

/>

3. Создайте папку для бандлинга (чтоб не путалось с исходниками): mkdir out

4. Сгенерите бандл (для того чтоб проще копать было, отключаем минификацию):

react-native bundle — entry-file index.js — platform android — dev false — minify false — bundle-output out/bundle.js — assets-dest out

5. Посмотрите, в каком виде у вас ассеты скомпилились и найдите в бандле то место, где данные о картинке лежат.

Потом с этими данными на руках посмотрим в код и сравним, как бы вы “руками” из ассетов картинку показывали.

Выполним эти команды. В качестве тестового фрагмента возьмем маркер для карт:

 point= 
source=
/>

После сборки бандла получаем не только собраный javascript файл, но и несколько папок с ресурсами, в которых не сложно найти наше изображение (в моем случае out/drawable-mdpi/app_ic.png). То есть в релизной сборке изображения все равно будут храниться в папке drawable и загружаться в нативном коде изображения будут одинаково.

Рассмотрим полученный javascript:

_react.default.createElement(_reactNativeYamap.Marker, point: i, 
source: _$$_REQUIRE(_dependencyMap[11])
>);

То есть в рендере вызывается некоторая функция _$$_REQUIRE. Если немного углубиться, то можно понять, что эта функция имеет некоторую сложность только при первом вызове, а при последующих просто будет возвращать поле объекта:

var module = modules[moduleIdReallyIsNumber];
return module && module.isInitialized ? module.publicModule.exports : guardedLoadModule(moduleIdReallyIsNumber, module);

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

Замечание

Обычно в своих проектах все изображения описываю в отдельном файле images.js:

export const MARKER = require(‘./ic.png’);

То есть во время работы приложения разницы между нативными и javascript ассетами не будет (но возможно немного замедлится запуск).

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

Плюсы

— IDE будет предлагать автоподстановку и автоимпорт для этой константы

— Удобно рефакторить — если поменяется имя файла или в процессе разработки решите сменить способ хранения ресурсов на нативные или наоборот

— Если изображение нигде не используется, то IDE подсветит неиспользуемую константу, что означает, что файл можно удалить (очень актуально для длительных сильно меняющихся проектов)

Минусы

— При таком подходе все импорты выполняются до начала выполнения, что теоретически замедляет запуск приложения

Выше мы получили следующий предварительный вывод — в релизе и дебаге изображения, которые мы достаем через import, отличаются. То есть в параметре source в нативный модуль будут приходить разные данные? То есть поведение в дебаге и релизе будет отличаться? — Да, оно действительно будет отличаться.

Рассмотрим проблему на примере конкретной задачи — реализовать нативный компонент, который бы принимал в props изображение любым способом, доступным компоненту Image.

В случае с require мы получаем просто число. Как из него в java коде получить изображение? Обратимся к коду компонента Image из react-native:

// In JS this is Image.props.source
@ReactProp(name = “src”)
public void setSource(ReactImageView view, @Nullable ReadableArray sources) view.setSource(sources);
>

Это единственное упоминание props.source, то есть в нативный компонент всегда приходит модель одного и того же вида. Возможно выполняется подготовка source перед передачей в нативный код. Вот она ( ̶к̶с̶т̶а̶т̶и̶,̶ ̶к̶т̶о̶-̶н̶и̶б̶у̶д̶ь̶ ̶з̶н̶а̶е̶т̶,̶ ̶п̶о̶ч̶е̶м̶у̶ ̶р̶е̶ш̶и̶л̶и̶ ̶р̶а̶з̶н̶е̶с̶т̶и̶ ̶н̶а̶ ̶2̶ ̶ф̶а̶й̶л̶а̶ ̶i̶o̶s̶/̶a̶n̶d̶r̶o̶i̶d̶,̶ ̶х̶о̶т̶я̶ ̶о̶н̶и̶ ̶и̶м̶е̶ю̶т̶ ̶н̶а̶в̶е̶р̶н̶о̶е̶ ̶о̶к̶о̶л̶о̶ ̶8̶0̶%̶ ̶о̶б̶щ̶е̶г̶о̶ ̶к̶о̶д̶а̶/̶к̶о̶п̶и̶п̶а̶с̶т̶а̶?̶)

let source = resolveAssetSource(props.source);

Для изображений, получаемых из javascript, функция вернет объект < uri: ‘http://localhost:8081/….’ >. То есть при дебаге изображения загружаются, как изображения из интернета. В релизе мы уже знаем, что будет получено имя drawable ресурса. Думаю достаточно интуитивно, что изображения из drawable и картинки из сети подготавливаются для отображения разными функциями, и, если работает один способ, это не значит, что будет работать другой.

Это объясняет например, почему defaultSource= для компонента Image работает только в релизной сборке (android).

В двух словах про ios:

resolveAssetSource для изображений из javascript возвращает < uri: ‘file:///Users/…’ >. То есть работа в дебаге и в релизе тоже отличается (загрузка файла из xcassets и из файла). Кроме того можно предположить, что работа с xcassets файлами как-то оптимизирована (знающие люди приглашаются в комментарии)

Итоги

Использование изображений из javascript:

  • Не требует сборки приложения при добавлении/изменении изображений
  • Отсутствует дублирование ресурсов под разные платформы
  • Разный принцип работы в дебаге и релизе
  • Небольшие накладные расходы на решение зависимостей (require)
  • При отладке ресурсы грузятся достаточно долго, что создает ощущение медленной работы приложения и портит настроение

Использование drawable/Images.xcassets изображений:

  • Одинаковая логика работы в релизе и дебаге
  • Отсутствие каких либо расходов на решение зависимостей
  • ̶О̶т̶к̶р̶ы̶в̶а̶я̶ ̶ф̶а̶й̶л̶ ̶I̶m̶a̶g̶e̶s̶.̶x̶c̶a̶s̶s̶e̶t̶s̶ ̶в̶ ̶X̶c̶o̶d̶e̶ ̶и̶ ̶д̶о̶б̶а̶в̶л̶я̶я̶ ̶р̶е̶с̶у̶р̶с̶ы̶ ̶в̶ ̶п̶а̶п̶к̶у̶ ̶r̶e̶s̶ ̶в̶ ̶а̶н̶д̶р̶о̶и̶д̶ ̶ч̶у̶в̶с̶т̶в̶у̶е̶ш̶ь̶ ̶с̶е̶б̶я̶ ̶н̶а̶т̶и̶в̶щ̶и̶к̶о̶м̶ ̶и̶ ̶р̶а̶с̶т̶е̶т̶ ̶с̶а̶м̶о̶о̶ц̶е̶н̶к̶а̶ (Шутка)
  • Дублирование ресурсов под разные платформы
  • Сборка при каждом изменении изображений

Использование изображений из assets (андроид):

Все то же самое, что и для drawable, но добавляется еще один минус:

Использование изображений в javascript коде будет выглядеть примерно так:

source= : < uri: ‘asset:/some_native_asset.png’ >>

что просто не удобно и создает дублирование кода.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *