327

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.

./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/.

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.

oklas
  • 7,935
  • 2
  • 26
  • 42
David Brierton
  • 6,977
  • 12
  • 47
  • 104
  • 4
    You need `../public/images/logo_2016.png` You went up twice, first out of the components folder, then out of the src folder. –  May 22 '17 at 13:44
  • 1
    ./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/. – David Brierton May 22 '17 at 13:45
  • My comment assumes that your `public` folder is directly inside your `src` folder. Your commentless comment features the old path starting with `../..` so not sure what your point is? –  May 22 '17 at 13:46
  • 7
    no public is on the same level as src – David Brierton May 22 '17 at 13:47
  • 2
    What they mean by "or add a symlink to it from project's node_modules/" ? – Julha May 23 '17 at 10:26
  • 1
    I answered this issue in detail at the question [symlink-node-modules-for-files-outside-src](https://stackoverflow.com/a/53045154/2013403) – its4zahoor Oct 29 '18 at 12:10
  • 1
    Possible duplicate of [Symlink node\_modules for files outside src](https://stackoverflow.com/questions/51357649/symlink-node-modules-for-files-outside-src) – Robert Columbia Oct 29 '18 at 14:20
  • 1
    You can read the documentation with pros and cons here: https://facebook.github.io/create-react-app/docs/using-the-public-folder – zurcacielos Jul 30 '19 at 21:00

32 Answers32

244

This is special restriction added by developers of create-react-app. It is implemented in ModuleScopePlugin to ensure files reside in src/. That plugin ensures that relative imports from app's source directory don't reach outside of it.

There is no official way to disable this feature except using eject and modify webpack config.

But, most features and its updates are hidden into the internals of create-react-app system. If you make eject you will have no more new 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 eject operation.

Play by the existing rules - move assets to src or use based on public folder url without import.


However instead of eject there are much unofficial solutions, based on rewire which allows you to programmatically modify the webpack config without eject. But removing the ModuleScopePlugin plugin is not good - this loses some protection and does not adds some features available in src. ModuleScopePlugin is designed to support multiple folders.

The better way is to add fully working additional directories similar to src also protected by ModuleScopePlugin. This can be done using react-app-alias


Anyway do not import from public folder - that will be duplicated in the build folder and will be available by two different url (and with different ways to load), which ultimately worsen the package download size.

Importing from the src folder is preferable and has advantages. Everything will be packed by webpack to the bundle with chunks optimal size and for best loading efficiency.

oklas
  • 7,935
  • 2
  • 26
  • 42
  • 12
    if you create symlink within ./src, and import from there -- the build does not work (babel plugin does not transform sources in symlinked folders). So with this restriction, on and no-symlink under src, you are effectively placed in a 'no-sharing-code-with-other-projects' jail (unless you choose completely emigrate/eject out of the CRA) – V P Apr 13 '18 at 05:57
  • 2
    @VP but the error says to "add a symlink to it from project's node_modules/.", does this not work? – adrianmcli Aug 05 '18 at 11:02
  • They should make a flag to disable this when running `create-react-app` for those who don't want to eject webpack config. Personally I always eject, but some people don't feel comfortable yet messing with webpacks daunting config. – TetraDev Aug 09 '18 at 21:08
  • 4
    @adrianmc. adding symlink from project's node_modules does not work, because many projects use share components/code that are not node_modules. For example I share code between React Native and React native web. Those 'snippets' are not node_modules, and these 2 projects actually have different node_modules. – V P Aug 21 '18 at 16:30
  • 4
    Can someone explain why the restriction was placed there in the first place, knowing this will determine if this answer is appropriate for my use case or not – rotimi-best May 01 '19 at 10:28
  • 12
    How is this the accepted answer? This bogus restriction is trivially eliminated by simply setting `NODE_PATH=./src/..` in the `.env` file. By doing so, you can import from outside of the src folder without going through the pain associated with ejecting your app. – Flaom May 06 '19 at 19:30
  • How about for .css file? how would that work with import? – Si8 Jul 31 '19 at 14:44
  • @Flaom That doesn't work anymore (if it actually used to work). You also get a deprecation warning for this variable. – adi518 Feb 17 '20 at 21:30
  • 1
    Looks like the baseUrl no longer works. Any attempt to set it outside of the source tree errors with: _Your project's `baseUrl` can only be set to `src` or `node_modules`. Create React App does not support other values at this time._ @Flaom's trick of prepending `./src` also doesn't help. – bluenote10 Apr 04 '20 at 20:32
  • @bluenote10 Just another reason to eject CRA. It used to work, no idea why they'd subtract from the ease of use that you can get with ./src/.. – Flaom Apr 08 '20 at 01:37
  • @oklas: I understand why this was implemented but as I want to keep my application secure I do not want multiple source files with the same content. In my case I'm talking about GraphQL queries... One is in the React application with Redux constants and the other is a Express application with Test constants... How do I solve this? I rather just have one location for my constants... – goldenmaza Nov 08 '20 at 15:49
  • @goldenmaza: Mentioned alias allows to map folder from another project (gives a way to access files from another project). Consider to test application behaviour (which performs queries) instead of query declarations testing. This way queries will be covered with tests. – oklas Nov 09 '20 at 04:28
  • @oklas: But then the two modules (frontend and backend) will be dependent on the eachother... I was hoping to place the queries in a third module and then both modules will be dependent on the third one instead... – goldenmaza Nov 09 '20 at 11:40
  • When two modules will be dependent on the eachother you can configure `src` from both as alias and import anything from both using alias. – oklas Nov 23 '20 at 05:02
  • as noted in a few of these comments, there are plenty of solutions that don't require the use of the destructive `eject` option - many of them are documented in the answers below – Avi Nerenberg Jun 20 '21 at 18:51
  • Is it possible to just remove the module and its references if I already uninstalled create-react-app from my project? – Ndrslmpk Nov 23 '21 at 23:30
77

The package react-app-rewired can be used to remove the plugin. This way you do not have to eject.

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.js file similar to this one:

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.

Lukas Bach
  • 3,559
  • 2
  • 27
  • 31
  • 9
    Great answer. You can leverage further `react-app-rewired` with [https://github.com/arackaf/customize-cra](customize-cra). Then the config will use just `babelInclude([path.resolve('src'), path.resolve('../common')])` and `removeModuleScopePlugin()`. – ivosh Apr 20 '19 at 10:20
  • can you please confirm where should i place this code snippet? – bijayshrestha Nov 03 '19 at 06:12
  • 1
    @bijayshrestha Read the readme file of the react-app-rewired project, there it explains how to set it up. During setup, you'll create a ``config-overrides.js`` file in which you can place the code. – Lukas Bach Nov 03 '19 at 18:23
  • 1
    Removing the `ModuleScopePlugin` plugin **is not a good** idea. It is better to add fully working additional directories similar to `src` using **[react-app-rewire-alias](https://github.com/oklas/react-app-rewire-alias)** – oklas Jun 02 '20 at 08:55
  • 5
    Does this solution work with Typescript? I cannot get it working with TS. –  Jul 02 '20 at 04:43
  • @user3053247 Do you want to have the config-overrides file in TS? react-app-rewired specifically looks for a JS file, so you'd have to precompile the config-overrides.ts to JS before starting the react app. Considering that the overrides file remains small, it's likely not worth it and easier to just have that file remain a JS file and keep the rest of the codebase in TS. – Lukas Bach Jul 03 '20 at 00:00
  • @oklas can you explain why it's not a bad idea? After some digging into an old CRA issue https://github.com/facebook/create-react-app/issues/834 it seems that the reason for it is because Babel doesn't run on anything outside the `src` directory. – Nabil Freeman Dec 23 '20 at 20:14
  • @NabilFreeman the reasons to restrict not wanted files by security and performance mentioned in [answer](https://stackoverflow.com/a/44115058/2969544) and other answers. This plugin and the babel is a part of configuration set where many other loaders, checkers, jest and etc features are configured and applied. There is no reason to explain the one feature by the another, when we considering the design of the whole configuration. Files with js may be processed without babel, here are also json, images and so on. – oklas Feb 13 '21 at 11:32
  • Added a copy&past [answer for Typescript users](https://stackoverflow.com/a/68017931/2072165) – panepeter Jun 17 '21 at 11:04
57

Remove it using 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;
    }
  }
};
nevace
  • 757
  • 6
  • 6
  • 3
    Vote for the craco! Craco supports CRA 3.x – Roman Podlinov May 18 '20 at 20:31
  • 6
    works beautifully in conjunction with this https://stackoverflow.com/a/58603207/2987400 – MikeW Feb 08 '21 at 13:27
  • 1
    To get it to work with TypeScript I needed this answer and the link MikeW posted. – Mitchell Tracy Mar 16 '21 at 20:31
  • Took this answer and combined it with [this gitlab comment](https://github.com/facebook/create-react-app/issues/9127#issuecomment-646989707) to get it working on Typescript. [Full solution as own answer](https://stackoverflow.com/a/68017931/2072165). – panepeter Jun 17 '21 at 11:05
  • @panepeter - your solution "works" but I'm having trouble importing a hook, react is complaining of the infamous "Error: Invalid hook call. Hooks can only be called inside of the body of a function component." I need to investigate more... – fullStackChris Dec 09 '21 at 19:36
  • @fullStackChris I don't think hooks and `craco` have any relation... That error is likely not related. The use of verbose tracing might help discover the underlying problem. – Urmzd Dec 10 '21 at 18:02
  • The error is definitely related. Its complaining because it detects two versions of React, the one where I'm importing my hook from and the one of my current create-react-app – fullStackChris Dec 11 '21 at 09:34
  • You can do this much cleaner in craco.config.js: webpack => plugins => remove like this: `remove: ['ModuleScopePlugin']` without the need to add it in the configure – A. Llorente Aug 02 '22 at 10:21
52

If your images are in the public folder then you should use

"/images/logo_2016.png"

in your <img> src instead of importing

'../../public/images/logo_2016.png'; 

This will work

<img className="Header-logo" src="/images/logo_2016.png" alt="Logo" />
Dmitry Yudakov
  • 15,364
  • 4
  • 49
  • 53
Abhinav bhardwaj
  • 2,657
  • 25
  • 21
  • 12
    Not working for me. Getting the same message - 'outside of the project src/ directory. Relative imports outside of src/ are not supported.' – Arkady Jan 11 '19 at 11:46
  • 4
    Your answer is correct IMO but I took the liberty of clarifying that you're talking about the path in ``, not importing it – Dmitry Yudakov Mar 16 '19 at 18:19
  • 3
    This was exactly what I was looking for! I simply added an "images" folder to my CRA's "src" directory, and then I was able to use `Logo` – Amos Long Aug 01 '19 at 05:14
  • 1
    @Arkady you might still have an import statement to your photo. Remove that import statement and just give direct path in the src attribute. – Yashwin Munsadwala Sep 14 '20 at 02:14
32

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:

  1. Use the module system (import x from y) provided with react-create-app and bundle it with your JS. Place the image inside the src folder.

  2. Serve it from the public folder 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.

Source: create-react-app

Edgar
  • 6,022
  • 8
  • 33
  • 66
danielgormly
  • 1,050
  • 1
  • 7
  • 16
  • 1
    Suggestion #2 is exactly what causes the following error for me: Module not found: You attempted to import ./../../../public/CheersBar-Drinks-147.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/. – Amos Long Aug 01 '19 at 05:01
29

There are a few answers that provide solutions with react-app-rewired, but customize-cra includes a removeModuleScopePlugin() API which is a bit more elegant. (It's the same solution, but abstracted away by the customize-cra package.)

npm i --save-dev react-app-rewired customize-cra

package.json

"scripts": {
    - "start": "react-scripts start"
    + "start": "react-app-rewired start",
    ...
},

config-overrides.js

const { removeModuleScopePlugin } = require('customize-cra')

module.exports = removeModuleScopePlugin()
Avi Nerenberg
  • 364
  • 4
  • 10
  • 4
    This saved my day! This should be the accepted answer if you're using something akin to [reactron](https://github.com/infinitered/reactotron)! – Abhishek Iyengar Jun 02 '21 at 13:13
24

I was able to import files outside of src/ by "copying" the outside files with file: as local dependency.

"dependencies": {
    "@my-project/outside-dist": "file:./../../../../dist".
}

then

import {FooComponent} from "@my-project/outside-dist/components";

No eject or react-app-rewired or other 3rd-party solution was needed.

fabpico
  • 2,628
  • 4
  • 26
  • 43
  • Hi, What if I am working with typescript? The `node_module` folder is ignored from build sources... – TOPKAT Apr 25 '22 at 12:47
  • 5
    This seems to work for packages, not standalone files. – adi518 Aug 24 '22 at 23:33
  • 1
    [NPM docs for *relative paths*](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#local-paths) – vsync Oct 17 '22 at 19:19
  • 1
    not working i got error :- Module not found: Error: Can't resolve – Deepak Singh Jan 02 '23 at 06:54
  • This works, however it only allows me to keep the installed package in a static state. Ie. I cant change the files outside the src directory and have the changes noticed, since npm essentially copies my cope from outside into my node modules, making a second copy of it – Bruce Mar 30 '23 at 00:02
15

You need to move WC-BlackonWhite.jpg into your src directory. The public directory 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.

Joe Clay
  • 33,401
  • 4
  • 85
  • 85
  • while this is a viable solution, the question is about enabling imports from outside of the `src` directory & not about conforming to the standard – Avi Nerenberg Jun 20 '21 at 18:49
10

I think Lukas Bach solution to use react-app-rewired in order to modify webpack config is a good way to go, however, I wouldn't exclude the whole ModuleScopePlugin but instead whitelist the specific file that can be imported outside of 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;
};
9

install these two packages

npm i --save-dev react-app-rewired customize-cra

package.json

"scripts": {
    - "start": "react-scripts start"
    + "start": "react-app-rewired start"
},

config-overrides.js

const { removeModuleScopePlugin } = require('customize-cra');

module.exports = function override(config, env) {
    if (!config.plugins) {
        config.plugins = [];
    }
    removeModuleScopePlugin()(config);

    return config;
};

Muhammad Numan
  • 23,222
  • 6
  • 63
  • 80
9

Copy-Paste Typescript solution

(e.g. this will work for a CRA/TS stack, which requires an additional step compared to CRA/JS. The solution itself is not typed.)

Adds the required paths to the ModuleScopePlugin instead of bluntly removing the plugin.

This code below is using craco, but should be easily usable for react-app-rewired or similar solutions. You just need to find the spot where you have a webpackConfig object (react-app-rewired: module.exports.webpack inside your config-overrides.js), and pass it to the provided functions.

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;

Taken from here and here

panepeter
  • 3,224
  • 1
  • 29
  • 41
7

Image inside public folder

  use image inside html extension
  <img src="%PUBLIC_URL%/resumepic.png"/>

  use image inside  js extension
  <img src={process.env.PUBLIC_URL+"/resumepic.png"}/>
  • use image inside js Extension
Yziaf_07
  • 7
  • 2
  • 6
5

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.

// 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

  1. either changing this piece of code (not recommended)
  2. or do eject then remove ModuleScopePlugin.js from the directory.
  3. or comment/remove const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); from ./node_modules/react-scripts/config/webpack.config.dev.js

PS: beware of the consequences of eject.

Community
  • 1
  • 1
its4zahoor
  • 1,709
  • 1
  • 16
  • 23
5

Adding to Bartek Maciejiczek's answer, this is how it looks with Craco:

const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
const path = require("path");

module.exports = {
  webpack: {
    configure: webpackConfig => {
      webpackConfig.resolve.plugins.forEach(plugin => {
        if (plugin instanceof ModuleScopePlugin) {
          plugin.allowedFiles.add(path.resolve("./config.json"));
        }
      });
      return webpackConfig;
    }
  }
};

My previous workaround worked with Webpack 4, but not with 5. After skimming through the accumulated workarounds since then, I found the following one really easy (and seemingly scalable).

import { CracoAliasPlugin } from 'react-app-alias';

const cracoConfig = {
  plugins: [
    {
      plugin: CracoAliasPlugin,
      options: {
        alias: { '~': './' },
      },
    },
  ],
}

Then import like so:

import whatever from '~/<path-to-file>';
adi518
  • 863
  • 1
  • 11
  • 19
3

I have had to overcome this same issue in Truffle. The solution was as follows:

ince Create-React-App's default behavior disallows importing files from outside of the src folder, we need to bring the contracts in our build folder inside src. We can copy and paste them every time we compile our contracts, but a better way is to simply configure Truffle to put the files there.

In the truffle-config.js file, replace the contents with the following:

const path = require("path");

module.exports = {
  contracts_build_directory: path.join(__dirname, "client/src/contracts")
};

I don't know if this helps you, but I know I found your question when I had the same issue in Truffle, and this might help someone else.

3

This can be done directly without using the path to the public folder. You can do it like

<img src="/images/image-name" alt=""/>

This happens because we do not use App.js in the browser. Since index.html is executed in the browser itself and the path to images is already in the public folder containing index.html file

shuberman
  • 1,416
  • 6
  • 21
  • 38
Ashish
  • 31
  • 4
3

This worked for me without installing/ changing anything

Context: I got this error when I tried to generate a build using yarn run build

Things I have done between the working and failing of yarn run build

I updated my ant-design to the latest stable version (v4.23.5).

Note: I highly believe that there is nothing to do with this version. I am just mentioning it to add more details.

  • This answer solved my issue. But I have changed no imports that access something outside the src directory.
  • The changes include updated package.json, yarn.lock, new Antd implementations (change in props mainly).
  • It made no sense why the build command broke/ why the answer is working.

Solution here

As all the changes are related to package.json, yarn.lock. I deleted node_modules and clean installed all the packages.

Run

yarn

or

npm install
Anjan Talatam
  • 2,212
  • 1
  • 12
  • 26
2

You don't need to eject, you can modify the react-scripts config with the rescripts library

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;
};
Lukas
  • 9,752
  • 15
  • 76
  • 120
2

Came to the same issue in my project, and found this in the official create-react-app docs: https://create-react-app.dev/docs/using-the-public-folder/

There is an "escape hatch" to add an asset outside the module system:

If you put a file into the public folder, it will not be processed by webpack. Instead it will be copied into the build folder untouched. To reference assets in the public folder, you need to use an environment variable called PUBLIC_URL.

Here's an example they provide:

render() {
  // Note: this is an escape hatch and should be used sparingly!
  // Normally we recommend using `import` for getting asset URLs
  // as described in “Adding Images and Fonts” above this section.
  return <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
1

If you only need to import a single file, such as README.md or package.json, then this can be explicitly added to ModuleScopePlugin()

config/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()
      ]),
    ]
  }
}
James McGuigan
  • 7,542
  • 4
  • 26
  • 29
1

the best solution is to fork react-scripts, this is actually mentioned in the official documentation, see: Alternatives to Ejecting

Fareed Alnamrouti
  • 30,771
  • 4
  • 85
  • 76
1

If you need multiple modifications, like when using ant design, you can combine multiple functions like this:

const {
  override,
  removeModuleScopePlugin,
  fixBabelImports,
} = require('customize-cra');

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css',
  }),
  removeModuleScopePlugin(),
);
1

You can try using simlinks, but in reverse.

React won't follow simlinks, but you can move something to the source directory, and create a simlink to it.

In the root of my project, I had a node server directory that had several schema files in it. I wanted to use them on the frontend, so I:

  • moved the files /src
  • in the termal, I cd'ed into where the schema files belonged in server
  • ln -s SRC_PATH_OF_SCHEMA_FILE

This gave react what it was looking for, and node was perfectly happy including files through simlinks.

RobKohr
  • 6,611
  • 7
  • 48
  • 69
1

If you want to access CSS files from the public, you might face an error OUTSIDE OF SOURCE DIRECTORY

Alternatively, you can link this file in index.html which also resides in the public directory.

<link rel="stylesheet" href="App.css">
maazakn
  • 384
  • 2
  • 10
1

Here's an alternative that works well in simple cases (using fs and ncp). While developing, keep a script running that watches for changes to your shared folder(s) outside of /src. When changes are made, the script can automatically copy the shared folder(s) to your project. Here's an example that watches a single directory recursively:


// This should be run from the root of your project

const fs = require('fs')
const ncp = require('ncp').ncp;

ncp.limit = 16

// Watch for file changes to your shared directory outside of /src
fs.watch('../shared', { recursive: true }, (eventType, filename) => {
    console.log(`${eventType}: ${filename}`)

    // Copy the shared folder straight to your project /src
    // You could be smarter here and only copy the changed file
    ncp('../shared', './src/shared', function(err) {
        if (err) {
          return console.error(err);
        }

        console.log('finished syncing!');
    });
})
a_schimpf
  • 745
  • 1
  • 5
  • 16
1

This is an issue with the relative import, which might have caused because we've used "create-react-app project" command which forms a directory named project with node_modules folder and several other files in public and src folders inside it. The create-react-app command puts a limitation that we can't import anything from outside src.

My Problem:

  1. I had to import react-bootstrap css files which are created in node_modules folder outside the src folder.
  2. I used import "../node_modules/bootstrap/dist/css/bootstrap.min.css"; but I got the error on terminal.
  3. I found out that I can create a new react app and follow solution steps from A to G, in order to fix this issue.

Solution: A) Create a new react app, using create-react-app new

B) cd new

C) run this command: "npm install react-bootstrap bootstrap@4.6.0" (without the "" double quotes )

D) in your react file put this to import bootstrap: D.1) import "../node_modules/bootstrap/dist/css/bootstrap.min.css"; or D.2)import Button from "react-bootstrap/Button";

E) create a bootstrap element like a Button or anything in your react file, for D.1) < button className="btn btn-success" > Bootstrap < /button> or for D.2) < Button variant="primary"> Bootstrap < /Button>

F) in terminal: cd src

G) in terminal: npm start,

this time it will be compiled successfully.

Reasoning: I could see react-bootstrap working finally once I followed steps A to G in order, and this time I didn't get any error. (I thought of this solution because:

  1. I've used npm install "@material-ui/icons" and that got installed in the node_modules folder outside the src.
  2. In my react file I've used import Add from "@material-ui/icons/Add"
  3. and Material-ui icons were working fine for me, but here also we are importing from outside src, from node_modules.. and everything works fine. Why there is no error of importing from outside src this time)
  4. That's why I just created a new react app, and followed solution steps A to G.
1

If you want to set a background image using CSS. So you have to set the image using the URL of your's localhost and add the path of your image. Just see the example below.

.banner {
  width: 100%;
  height: 100vh;
  background-image: url("http://localhost:3000/img/bg.jpg");
  background-size: cover;
  background-repeat: no-repeat;
}
HandyPawan
  • 1,018
  • 1
  • 11
  • 16
  • This will result in necessary code change for production deployment. Better to use base url as an environment variable. – Harikrishnan May 06 '22 at 06:49
1

Posting here what @Flaom wrote as a comment in the marked as reply answer and that actually saves lives:

"How is this the accepted answer? This bogus restriction is trivially eliminated by simply setting NODE_PATH=./src/.. in the .env file. By doing so, you can import from outside of the src folder without going through the pain associated with ejecting your app. "

  • Flaom

EDIT Added some more info as @cigien requested.

All the answers above describe very well why we cannot use an image from the public folder when we create our react app with the create-react-app. Having the issue myself and reading all these answers I realized that, what the answers say is to "hack" the app in order to remove the module that restricts us. Some of the answers don't even have an undo option. For a "training" application that is ok.

Personally I would not want to add a solution that alters the concept of the app to my own project, specially in a commercial one. @Flaom solution is the simplest and if anything change in the future it can be replaced with another solution. It has no risk, it can be removed anytime and is the simplest.

  • Could you add some additional information in your own words as to why the quoted comment addresses the OPs question? – cigien Oct 09 '21 at 16:19
  • A `.env` file is not supposed to be committed, so it's not trivial to ensure this fix works for everyone in a team. – adi518 Aug 25 '22 at 00:36
1

If you file reside in public folder and if you want to import it without eject or without using react-app-rewired then in that case you can access file via domains name and the path of the file and using axios. Example: There is a font file called favico.ico located inside public folder. You want to import it in one the file located in src. You can access the font using following logic.

axios.get('example.com/favico.ico').then(() => {
  // here you can access this file.
})

In above example example.com is domain. If you have different environment like localhost, staging, production then in that case the domain name is different. So, to get the favico.ico you can use following logic.

axios.get(`${window.location.origin}/favico.ico`).then(() => {
  // here you can access this file.
})

In above example you window.location.origin give you current domain meaning if you run your code locally then, it will give you http://localhost:{portnumber}, If your code run on production and production domain is example.com then, it will give you "example.com". So using this pattern you can access assets located in public folder.

mahekj
  • 11
  • 2
1

If you want an easier solution to this just import the media inside your src folder like this:

import photo from "./assets/yourphoto.jpeg"

then you can implement it like this:

<img className="photo src={photo} alt="installation" />

So then the app tree goes: -src folder -- assets folder --- yourphoto.jpeg

chillcoder
  • 21
  • 3
-1

This was my code:

import React from 'react';

import './Navbar.scss';
import {images} from '../../constants';
const Navbar = () => {
    return (
        <nav>
            <div>
                < img src = {images.logo} alt = "logo" />

            </div>

        </nav>
    );
}

export default Navbar;

Changed it too:

import React from 'react';

import './Navbar.scss';
import {images} from '././constants';
const Navbar = () => {
    return (
        <nav>
            <div>
                < img src = {images.logo} alt = "logo" />

            </div>

        </nav>
    );
}

export default Navbar;

And it worked! Im getting better at fixing bugs haha.

-4

So apparently, using Create-react-app will restrict you from accessing Images outside the root directory of your project - usually src.

A quick fix for this is to move your images from the public folder to the src folder and you are good to go.
So your code will be like this for example:

background-image: URL('/src/images/img-2.jpg');
nima
  • 7,796
  • 12
  • 36
  • 53
Adam Alex
  • 1
  • 3