Ограничение импорта приложений create-react-app вне каталога src
Я использую приложение create-react-app. Я пытаюсь вызвать изображение из моей общей папки из файла внутри моего src/components
. Я получаю это сообщение об ошибке.
./src/components/website_index.js Модуль не найден: вы пытались импорт.. /../public/images/logo/WC-BlackonWhite.jpg который падает вне директории проекта src/. Относительный импорт за пределами src/не поддерживаются. Вы можете либо переместить его внутри src/, либо добавить символическая ссылка на него из проекта node_modules/.
import logo from '../../public/images/logo_2016.png';
<img className="Header-logo" src={logo} alt="Logo" />
Я читал много вещей, говорящих, что вы можете импортировать путь, но это все еще не работает для меня. Любая помощь будет принята с благодарностью. Я знаю, что есть много таких вопросов, но они все говорят мне импортировать логотип или изображение так ясно, что у меня что-то отсутствует в общей картине.
Ответы
Ответ 1
Это специальное ограничение, добавленное разработчиками create-реагировать на приложение. Он реализован в ModuleScopePlugin
, чтобы гарантировать, что файлы находятся в src/
. Этот плагин гарантирует, что относительный импорт из исходного каталога приложения не будет достигнут за его пределами.
Вы можете отключить эту функцию, но только после операции eject
проекта create-реагировать на приложение.
Большинство функций и их обновлений скрыты во внутренней части системы create-реагировать-приложение. Если вы сделаете eject
, у вас больше не будет некоторых функций и его обновления. Поэтому, если вы не готовы управлять приложением и настраивать его для настройки веб-пакета и т.д., Не выполняйте операцию eject
.
Играть по существующим правилам (перейти на src). Но теперь вы можете знать, как снять ограничение: сделайте eject
и удалите ModuleScopePlugin
из файла конфигурации веб-пакета.
Поскольку create-реагировать-приложение v0.4.0 переменная среды NODE_PATH
позволяет указать путь для абсолютного импорта.
Абсолютный импорт позволяет использовать import App from 'App'
вместо import App from './App'
относительно значения, указанного в переменной NODE_PATH
.
Эта функция особенно полезна для monorepos или других вопросов конфигурации, но не для импорта изображений или чего-либо еще из папки public
.
Содержимое папки public
будет помещено в папку build
и доступно по относительному URL. Кроме того, все импортированное будет обработано веб-пакетом и будет также помещено в папку build
.
Если вы импортируете что-либо из папки public
, вероятно, эта вещь будет дублирована в папке build
и будет доступна по двум разным URL (или с разными способами загрузки), что в конечном итоге ухудшит размер загружаемого пакета.
Импорт из папки src предпочтителен и имеет свои преимущества. Все будет упаковано с помощью веб-пакета в пакет с кусками оптимального размера и для лучшей эффективности загрузки.
Ответ 2
Чтобы предложить немного больше информации для других ответов. У вас есть два варианта, как доставить файл .png пользователю. Структура файла должна соответствовать выбранному вами методу. Два варианта:
Используйте модульную систему (import x from y
), поставляемую с Reaction-Create-App, и объедините ее с JS. Поместите изображение в папку src
.
Подайте его из папки public
и позвольте Node обслуживать файл. create-реагировать-приложение также, очевидно, поставляется с переменной окружения, например, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;
. Это означает, что вы можете ссылаться на него в своем приложении React, но при этом он будет обслуживаться через Node, а ваш браузер запрашивает его отдельно в обычном GET-запросе.
Источник: создать-реагировать-приложение
Ответ 3
Пакет response-app-rewired можно использовать для удаления плагина. Таким образом, вы не должны извлечь.
Следуйте инструкциям на странице пакета npm (установите пакет и переверните вызовы в файле package.json) и используйте файл config-overrides.js
подобный этому:
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
module.exports = function override(config, env) {
config.resolve.plugins = config.resolve.plugins.filter(plugin => !(plugin instanceof ModuleScopePlugin));
return config;
};
Это удалит ModuleScopePlugin из используемых плагинов WebPack, но оставит все как есть и устранит необходимость извлечения.
Ответ 4
Если ваши изображения находятся в общей папке, то вы должны использовать
"/images/logo_2016.png"
в вашем <img>
src
вместо импорта
'../../public/images/logo_2016.png';
Это будет работать
<img className="Header-logo" src="/images/logo_2016.png" alt="Logo" />
Ответ 5
Вам нужно переместить WC-BlackonWhite.jpg
в ваш каталог src
. public
каталог предназначен для статических файлов, которые будут связаны напрямую в HTML (например, в значке), а не для материалов, которые вы собираетесь импортировать непосредственно в ваш пакет.
Ответ 6
Это ограничение гарантирует, что все файлы или модули (экспорт) находятся в каталоге src/
, реализация находится в ./node_modules/react-dev-utils/ModuleScopePlugin.js
, в следующих строках кода.
// Resolve the issuer from our appSrc and make sure it one of our files
// Maybe an indexOf === 0 would be better?
const relative = path.relative(appSrc, request.context.issuer);
// If it not in src/ or a subdirectory, not our request!
if (relative.startsWith('../') || relative.startsWith('..\\')) {
return callback();
}
Вы можете снять это ограничение с помощью
- либо изменить этот кусок кода (не рекомендуется)
- или же
eject
затем удалить ModuleScopePlugin.js
из каталога. - или прокомментируйте/удалите
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
из ./node_modules/react-scripts/config/webpack.config.dev.js
PS: остерегайтесь последствий выброса.
Ответ 7
Вам не нужно извлекать, вы можете изменить конфигурацию react-scripts
с помощью библиотеки сценариев
Это будет работать тогда:
module.exports = config => {
const scopePluginIndex = config.resolve.plugins.findIndex(
({ constructor }) => constructor && constructor.name === "ModuleScopePlugin"
);
config.resolve.plugins.splice(scopePluginIndex, 1);
return config;
};
Ответ 8
Если вам нужно импортировать только один файл, такой как README.md или package.json, это можно явно добавить в ModuleScopePlugin()
конфиг /paths.js
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
module.exports = {
appPackageJson: resolveApp('package.json'),
appReadmeMD: resolveApp('README.md'),
};
config/webpack.config.dev.js + config/webpack.config.prod.js
module.exports = {
resolve: {
plugins: [
// Prevents users from importing files from outside of src/ (or node_modules/).
// This often causes confusion because we only process files within src/ with babel.
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc, [
paths.appPackageJson,
paths.appReadmeMD // README.md lives outside of ./src/ so needs to be explicitly included in ModuleScopePlugin()
]),
]
}
}
Ответ 9
Лучшее решение - это разветкить react-scripts
, это на самом деле упоминается в официальной документации, см. Альтернативы Ejecting.
Ответ 10
Я думаю, что решение Лукаса Баха использовать реагировать на приложения для изменения конфигурации веб-пакета - это хороший путь, однако я не исключаю всего ModuleScopePlugin но вместо этого внесите в белый список конкретный файл, который можно импортировать за пределы src:
конфиг-overrides.js
const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
const path = require("path");
module.exports = function override(config) {
config.resolve.plugins.forEach(plugin => {
if (plugin instanceof ModuleScopePlugin) {
plugin.allowedFiles.add(path.resolve("./config.json"));
}
});
return config;
};