Компонент 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

Если собираете на 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
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 Автор вопроса
Мда, React точно не для людей делали ))

Влад @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
поместил изображение в папку с компонентом
файл лежит в ./components/UserId/img/johnson.jpg или ./components/UserId/johnson.jpg ?

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

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

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

Влад @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
Влад, попробуй сделать проще
используй usehistory
с помощью этого хука получаешь доступ к history
а у него используешь метод goBack()
import < useHistory >from "react-router-dom"; const history = useHistory() return ( );

Влад @Vextor-ltd Автор вопроса
Иван В, а что касается изображений? Поместить их в public?
Ладно, пойду читать что-то типа структурирования React-приложений.

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

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

Иван В @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’ >>
что просто не удобно и создает дублирование кода.