Javascript src 目录之外的 create-react-app 导入限制
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44114436/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The create-react-app imports restriction outside of src directory
提问by David Brierton
I am using create-react-app. I am trying to call an image from my public folder from a file inside my src/components. I am receiving this error message.
我正在使用 create-react-app。我正在尝试从我的src/components. 我收到此错误消息。
./src/components/website_index.js Module not found: You attempted to import ../../public/images/logo/WC-BlackonWhite.jpg which falls outside of the project src/ directory. Relative imports outside of src/ are not supported. You can either move it inside src/, or add a symlink to it from project's node_modules/.
./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" />
import logo from '../../public/images/logo_2016.png';
<img className="Header-logo" src={logo} alt="Logo" />
I have read many things saying you can do an import to the path but that is still not working for me. Any help would be greatly appreciated. I know there are many questions like this but they are all telling me to import logo or image so clearly I am missing something in the big picture.
我读过很多东西说你可以对路径进行导入,但这对我来说仍然不起作用。任何帮助将不胜感激。我知道有很多这样的问题,但它们都告诉我要导入徽标或图像,所以很明显我在大局中遗漏了一些东西。
采纳答案by oklas
This is special restriction added by developers of create-react-app. It is implemented in ModuleScopePluginto ensure files reside in src/. That plugin ensures that relative imports from app's source directory don't reach outside of it.
这是 create-react-app 的开发者添加的特殊限制。它被实现ModuleScopePlugin以确保文件驻留在src/. 该插件确保来自应用程序源目录的相对导入不会到达它之外。
You can disable this feature but only after ejectoperation of create-react-app project.
您可以禁用此功能,但必须在ejectcreate-react-app 项目运行后才能禁用。
Most features and its updates are hidden into the internals of create-react-app system. If you make ejectyou will no more have some features and its update. So if you are not ready to manage and configure application included to configure webpack and so on - do not do ejectoperation.
大多数功能及其更新都隐藏在 create-react-app 系统的内部。如果您制作,eject您将不再拥有某些功能及其更新。所以如果你还没有准备好管理和配置包含的应用程序来配置 webpack 等等 - 不要做eject操作。
Play by the existing rules (move to src). But now you can know how to remove restriction: do ejectand remove ModuleScopePluginfrom webpack configuration file.
按照现有规则进行操作(移至 src)。但是现在你可以知道如何移除限制了:do ejectand remove ModuleScopePluginfrom webpack configuration file。
Since create-react-appv0.4.0the NODE_PATHenvironment variable allows to specify a path for absolute import. And since v3.0.0NODE_PATHis deprecated in favor of setting baseUrlin jsconfig.jsonor tsconfig.json.
由于创建反应的应用程序内V0.4.0的NODE_PATH环境变量允许指定绝对导入的路径。并且由于v3.0.0NODE_PATH已被弃用,以支持baseUrl在jsconfig.json或中设置tsconfig.json。
Absolute import allows using import App from 'App'instead import App from './App'relative to the value specified in base url.
绝对进口允许使用import App from 'App'代替import App from './App'相对于在基本URL指定的值。
This feature is specifically useful for monorepos or other configuration questions but not for importing images or anything else from publicfolder.
此功能对于 monorepos 或其他配置问题特别有用,但不适用于从public文件夹导入图像或其他任何内容。
Content of publicfolder will be placed in buildfolder and available by relative url. Also, everything imported will be processed by webpack and will be placed also in buildfolder.
public文件夹的内容将放置在build文件夹中,并通过相对 url 可用。此外,导入的所有内容都将由 webpack 处理,并且也会放置在build文件夹中。
If you import something from publicfolder probably that thing will be duplicated in the buildfolder and will be available by two different url (or with different ways to load), which ultimately worsen the package download size.
如果您从public文件夹导入某些内容,则该内容可能会在build文件夹中复制,并且可以通过两个不同的 url(或使用不同的加载方式)访问,这最终会恶化包下载的大小。
Importing from the srcfolder is preferable and has advantages. Everything will be packed by webpack to the bundle with chunks optimal sizeand for best loading efficiency.
从 src文件夹导入是可取的并且具有优势。一切都将被 webpack 打包到具有最佳大小和最佳加载效率的块的包中。
There are intermediate solutions, namely the rewiresystem which allows you to programmatically modify the webpack config. But removingthe ModuleScopePluginplugin is not a goodsolution; it is better to add fully working additional directories similar to src.
有中间方案,即再布线系统,它允许您以编程方式修改的WebPack配置。但除去该ModuleScopePlugin插件是不是一个很好的解决方案; 最好添加类似于src.
Currently, create-react-appdoes not support additional directories other than srcin the root folder. This can be done using react-app-rewire-alias
目前,create-react-app不支持src除根文件夹之外的其他目录。这可以使用react-app-rewire-alias来完成
回答by Lukas Bach
The package react-app-rewiredcan be used to remove the plugin. This way you do not have to eject.
包react-app-rewired可用于删除插件。这样您就不必弹出。
Follow the steps on the npm package page (install the package and flip the calls in the package.json file) and use a config-overrides.jsfile similar to this one:
按照 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;
};
This will remove the ModuleScopePlugin from the used WebPack plugins, but leave the rest as it was and removes the necessity to eject.
这将从使用的 WebPack 插件中删除 ModuleScopePlugin,但保留其余部分并消除弹出的必要性。
回答by danielgormly
To offer a little bit more information to other's answers. You have two options regarding how to deliver the .png file to the user. The file structure should conform to the method you choose. The two options are:
为其他人的答案提供更多信息。关于如何将 .png 文件交付给用户,您有两种选择。文件结构应符合您选择的方法。这两个选项是:
Use the module system (
import x from y) provided with react-create-app and bundle it with your JS. Place the image inside thesrcfolder.Serve it from the
publicfolder and let Node serve the file. create-react-app also apparently comes with an environment variable e.g.<img src={process.env.PUBLIC_URL + '/img/logo.png'} />;. This means you can reference it in your React app but still have it served through Node, with your browser asking for it separately in a normal GET request.
使用
import x from yreact-create-app 提供的模块系统 ( ) 并将其与您的 JS 捆绑在一起。将图像放在src文件夹中。从
public文件夹中提供它,让 Node 提供文件。create-react-app 显然也带有一个环境变量,例如<img src={process.env.PUBLIC_URL + '/img/logo.png'} />;. 这意味着你可以在你的 React 应用程序中引用它,但仍然通过 Node 提供它,你的浏览器在普通的 GET 请求中单独请求它。
Source: create-react-app
来源:创建反应应用程序
回答by Abhinav bhardwaj
If your images are in the public folder then you should use
如果您的图像在公共文件夹中,那么您应该使用
"/images/logo_2016.png"
in your <img>srcinstead of importing
在你<img>src而不是进口
'../../public/images/logo_2016.png';
This will work
这将工作
<img className="Header-logo" src="/images/logo_2016.png" alt="Logo" />
回答by Joe Clay
You need to move WC-BlackonWhite.jpginto your srcdirectory. The publicdirectory is for static files that's going to be linked directly in the HTML (such as the favicon), not stuff that you're going to import directly into your bundle.
你需要WC-BlackonWhite.jpg进入你的src目录。该public目录用于存放将直接在 HTML 中链接的静态文件(例如收藏夹图标),而不是您将直接导入到包中的内容。
回答by Avi Nerenberg
There are a few answers that provide solutions with react-app-rewired, but customize-craexposes a special removeModuleScopePlugin()API which is a bit more elegant. (It's the same solution, but abstracted away by the customize-crapackage.)
有一些答案提供了 解决方案react-app-rewired,但customize-cra公开了removeModuleScopePlugin()一个更优雅的特殊API。(这是相同的解决方案,但被customize-cra包抽象掉了。)
npm i --save-dev react-app-rewired customize-cra
npm i --save-dev react-app-rewired customize-cra
package.json
包.json
"scripts": {
- "start": "react-scripts start"
+ "start": "react-app-rewired start",
...
},
config-overrides.js
config-overrides.js
const { removeModuleScopePlugin } = require('customize-cra')
module.exports = removeModuleScopePlugin()
回答by nevace
Remove it using Craco:
使用 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;
}
}
};
回答by its4zahoor
This restriction makes sure all files or modules (exports) are inside src/directory, the implementation is in ./node_modules/react-dev-utils/ModuleScopePlugin.js, in following lines of code.
此限制确保所有文件或模块(导出)都在src/目录中,实现在./node_modules/react-dev-utils/ModuleScopePlugin.js, 在以下代码行中。
// Resolve the issuer from our appSrc and make sure it's one of our files
// Maybe an indexOf === 0 would be better?
const relative = path.relative(appSrc, request.context.issuer);
// If it's not in src/ or a subdirectory, not our request!
if (relative.startsWith('../') || relative.startsWith('..\')) {
return callback();
}
You can remove this restriction by
您可以通过以下方式取消此限制
- either changing this piece of code (not recommended)
- or do
ejectthen removeModuleScopePlugin.jsfrom the directory. - or comment/remove
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');from./node_modules/react-scripts/config/webpack.config.dev.js
- 要么改变这段代码(不推荐)
- 或做
eject然后取出ModuleScopePlugin.js从目录。 - 或评论/删除
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');从./node_modules/react-scripts/config/webpack.config.dev.js
PS: beware of the consequences of eject.
PS:注意eject的后果。
回答by Lukas
You don't need to eject, you can modify the react-scriptsconfig with the rescripts library
不需要eject,可以react-scripts用rescripts库修改config
This would work then:
这将起作用:
module.exports = config => {
const scopePluginIndex = config.resolve.plugins.findIndex(
({ constructor }) => constructor && constructor.name === "ModuleScopePlugin"
);
config.resolve.plugins.splice(scopePluginIndex, 1);
return config;
};
回答by Bartek Maciejiczek
I think Lukas Bach solutionto use react-app-rewiredin order to modify webpack config is a good way to go, however, I wouldn't exclude the whole ModuleScopePluginbut instead whitelist the specific file that can be imported outside of src:
我认为Lukas Bach 解决方案使用react-app-rewired 来修改 webpack 配置是一个很好的方法,但是,我不会排除整个ModuleScopePlugin而是将可以在 src 之外导入的特定文件列入白名单:
config-overrides.js
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;
};

