جاوااسکریپت - محدودیت وارد کردن create-react-app خارج از پوشه src
من از create-react-app استفاده میکنم. من در تلاش هستم تا تصویری را از پوشه public خود از فایلی در داخل 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';
من چیزهای زیادی خواندهام که میگویند میتوانید یک وارد کردن به مسیر انجام دهید، اما این هنوز برای من کار نمیکند. هر کمکی بسیار قدردانی خواهد شد. میدانم که سوالات زیادی مانند این وجود دارد اما همه به من میگویند لوگو یا تصویر را وارد کنم، بنابراین واضح است که چیزی در تصویری بزرگتر از دستم رفته است.
پاسخ شماره ۱
این محدودیت ویژه توسط توسعهدهندگان create-react-app اضافه شده است. این محدودیت در ModuleScopePlugin پیادهسازی شده تا اطمینان حاصل شود فایلها در src/ قرار دارند. این افزونه تضمین میکند که واردات نسبی از دایرکتوری منبع برنامه به خارج از آن نرسد.
هیچ راه رسمی برای غیرفعال کردن این ویژگی وجود ندارد مگر اینکه از eject استفاده کرده و پیکربندی webpack را تغییر دهید.
اما بیشتر ویژگیها و بهروزرسانیهای آن در بخشهای داخلی سیستم create-react-app پنهان شدهاند. اگر eject انجام دهید، دیگر ویژگیها و بهروزرسانیهای جدید نخواهید داشت. بنابراین اگر آماده مدیریت و پیکربندی برنامه شامل پیکربندی webpack و غیره نیستید - عملیات eject را انجام ندهید.
طبق قوانین موجود بازی کنید - داراییها را به src منتقل کنید یا بر اساس URL پوشه public بدون وارد کردن استفاده کنید.
با این حال، به جای eject راهحلهای غیررسمی زیادی وجود دارد که بر اساس rewire هستند و به شما اجازه میدهند به صورت برنامهنویسی شده پیکربندی webpack را بدون eject تغییر دهید. اما حذف پلاگین ModuleScopePlugin خوب نیست - این بعضی از محافظتها را از دست میدهد و قابلیتهایی که در src موجود هستند را اضافه نمیکند. ModuleScopePlugin برای پشتیبانی از چند فولدر طراحی شده است.
راه بهتر این است که دایرکتوریهای اضافی کاملاً کارآمد مشابه src اضافه کنید که همچنین توسط ModuleScopePlugin محافظت میشوند. این کار میتواند با استفاده از react-app-alias انجام شود
به هر حال از پوشه public وارد نکنید - این در پوشه build تکرار خواهد شد و از طریق دو URL مختلف قابل دسترسی خواهد بود (و با روشهای مختلف بارگیری)، که در نهایت اندازه دانلود بسته را بدتر میکند.
وارد کردن از پوشه src ترجیح داده میشود و مزایایی دارد. همه چیز توسط webpack به بسته با بخشهایی با اندازه بهینه و برای کارآمدترین بارگذاری بستهبندی خواهد شد.
پاسخ شماره ۲
بسته react-app-rewired میتواند برای حذف پلاگین استفاده شود. به این ترتیب نیازی به eject کردن ندارید.
مراحل صفحه بسته 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 حذف شود، اما بقیه همانطور که بود باقی بماند و نیاز به eject کردن را از بین ببرد.
پاسخ شماره ۳
با استفاده از Craco آن را حذف کنید:
module.exports = {
webpack: {
configure: webpackConfig => {
const scopePluginIndex = webpackConfig.resolve.plugins.findIndex(
({ constructor }) => constructor && constructor.name === 'ModuleScopePlugin'
);
webpackConfig.resolve.plugins.splice(scopePluginIndex, 1);
return webpackConfig;
}
}
};
پاسخ شماره ۴
اگر تصاویر شما در پوشه عمومی هستند، پس باید از آن استفاده کنید
"/images/logo_2016.png"
در <img> src خود به جای وارد کردن
'../../public/images/logo_2016.png';
این کار خواهد کرد
<img className="Header-logo" src="/images/logo_2016.png" alt="Logo" />
پاسخ شماره ۵
برای ارائه اطلاعات کمی بیشتر به پاسخهای دیگران. شما دو گزینه در مورد چگونگی ارائه فایل .png به کاربر دارید. ساختار فایل باید با روشی که انتخاب میکنید مطابقت داشته باشد. دو گزینه عبارتند از:
از سیستم ماژول (
import x from y) ارائهشده با react-create-app استفاده کنید و آن را همراه با JS خود بستهبندی کنید. تصویر را در داخل پوشهsrcقرار دهید.آن را از پوشه
publicسرو کنید و بگذارید Node فایل را سرو کند. ظاهراً create-react-app همچنین با یک متغیر محیطی همراه است، مثلاً<img src={process.env.PUBLIC_URL + '/img/logo.png'} />;. این بدان معنی است که شما میتوانید به آن در برنامه React خود اشاره کنید اما همچنان آن از طریق Node سرو میشود، و مرورگر شما آن را به صورت جداگانه در یک درخواست GET معمولی درخواست میکند.
منبع: create-react-app
پاسخ شماره ۶
چند جواب وجود دارد که راهحلهایی با react-app-rewired ارائه میدهند، اما customize-cra شامل یک API به نام removeModuleScopePlugin() است که کمی شیکتر است. (این همان راهحل است، اما توسط بسته customize-cra انتزاعی شده است.)
npm i --save-dev react-app-rewired customize-craپکیج.جیسان
"scripts": {
- "start": "react-scripts start"
+ "start": "react-app-rewired start",
...
},
config-overrides.js
const { removeModuleScopePlugin } = require('customize-cra')
module.exports = removeModuleScopePlugin()
پاسخ شماره ۷
من توانستم فایلهای خارج از src/ را با «کپی کردن» فایلهای بیرونی با file: به عنوان وابستگی محلی وارد کنم.
"dependencies": {
"@my-project/outside-dist": "file:./../../../../dist".
}
سپس
import {FooComponent} from "@my-project/outside-dist/components";
هیچ eject یا react-app-rewired یا راهحل شخص ثالث دیگری مورد نیاز نبود.
پاسخ شماره ۸
شما باید فایل WC-BlackonWhite.jpg را به دایرکتوری src خود منتقل کنید. دایرکتوری public برای فایلهای ثابت است که مستقیماً در HTML لینک میشوند (مانند favicon) و برای مواردی که مستقیماً به بسته شما وارد میکنید، نیست.
پاسخ شماره ۹
راهحل Typescript کپی-پیست
(به عنوان مثال، این برای یک پشته CRA/TS کار خواهد کرد، که در مقایسه با CRA/JS نیاز به یک مرحله اضافی دارد. خود راهحل تایپ نشده است.)
مسیرهای مورد نیاز را به ModuleScopePlugin اضافه میکند به جای اینکه به طور کامل پلاگین را حذف کند.
کد زیر از craco استفاده میکند، اما باید به راحتی برای react-app-rewired یا راهحلهای مشابه قابل استفاده باشد. شما فقط نیاز دارید قسمتی را پیدا کنید که یک شیء webpackConfig دارید (react-app-rewired: module.exports.webpack داخل config-overrides.js خود)، و آن را به توابع ارائه شده ارسال کنید.
craco.config.js
const path = require("path");
const enableImportsFromExternalPaths = require("./src/helpers/craco/enableImportsFromExternalPaths");
// Paths to the code you want to use
const sharedLibOne = path.resolve(__dirname, "../shared-lib-1/src");
const sharedLibTwo = path.resolve(__dirname, "../shared-lib-2/src");
module.exports = {
plugins: [
{
plugin: {
overrideWebpackConfig: ({ webpackConfig }) => {
enableImportsFromExternalPaths(webpackConfig, [
// Add the paths here
sharedLibOne,
sharedLibTwo,
]);
return webpackConfig;
},
},
},
],
};
helpers/craco/enableImportsFromExternalPaths.js
const findWebpackPlugin = (webpackConfig, pluginName) =>
webpackConfig.resolve.plugins.find(
({ constructor }) => constructor && constructor.name === pluginName
);
const enableTypescriptImportsFromExternalPaths = (
webpackConfig,
newIncludePaths
) => {
const oneOfRule = webpackConfig.module.rules.find((rule) => rule.oneOf);
if (oneOfRule) {
const tsxRule = oneOfRule.oneOf.find(
(rule) => rule.test && rule.test.toString().includes("tsx")
);
if (tsxRule) {
tsxRule.include = Array.isArray(tsxRule.include)
? [...tsxRule.include, ...newIncludePaths]
: [tsxRule.include, ...newIncludePaths];
}
}
};
const addPathsToModuleScopePlugin = (webpackConfig, paths) => {
const moduleScopePlugin = findWebpackPlugin(
webpackConfig,
"ModuleScopePlugin"
);
if (!moduleScopePlugin) {
throw new Error(
`Expected to find plugin "ModuleScopePlugin", but didn't.`
);
}
moduleScopePlugin.appSrcs = [...moduleScopePlugin.appSrcs, ...paths];
};
const enableImportsFromExternalPaths = (webpackConfig, paths) => {
enableTypescriptImportsFromExternalPaths(webpackConfig, paths);
addPathsToModuleScopePlugin(webpackConfig, paths);
};
module.exports = enableImportsFromExternalPaths;
گرفته شده از اینجا و اینجا 🙏
پاسخ شماره ۱۰
من فکر میکنم راهحل لوکاس باخ برای استفاده از react-app-rewired به منظور تغییر تنظیمات webpack روش خوبی است، با این حال، من کل ModuleScopePlugin را کنار نمیگذارم و به جای آن فایل خاصی که میتواند خارج از src وارد شود را در لیست سفید قرار میدهم:
config-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;
};
