The create-react-app imports restriction outside of src directory

354,830

Solution 1

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.

Solution 2

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.

Solution 3

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;
    }
  }
};

Solution 4

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

Solution 5

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

Share:
354,830

Related videos on Youtube

David Brierton
Author by

David Brierton

Updated on March 06, 2022

Comments

  • David Brierton
    David Brierton about 2 years

    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.

    • ChrisG
      ChrisG about 7 years
      You need ../public/images/logo_2016.png You went up twice, first out of the components folder, then out of the src folder.
    • David Brierton
      David Brierton about 7 years
      ./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/.
    • ChrisG
      ChrisG about 7 years
      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?
    • David Brierton
      David Brierton about 7 years
      no public is on the same level as src
    • Julha
      Julha about 7 years
      What they mean by "or add a symlink to it from project's node_modules/" ?
    • its4zahoor
      its4zahoor over 5 years
      I answered this issue in detail at the question symlink-node-modules-for-files-outside-src
    • Robert Columbia
      Robert Columbia over 5 years
    • 1P0
      1P0 almost 5 years
      You can read the documentation with pros and cons here: facebook.github.io/create-react-app/docs/…
  • David Brierton
    David Brierton about 7 years
    I have seen others do it this way. Thats why I thought this is the proper way
  • Joe Clay
    Joe Clay about 7 years
    @DavidBrierton: This precaution might have been added in a more recent version of create-react-app.
  • V P
    V P about 6 years
    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)
  • adrianmc
    adrianmc almost 6 years
    @VP but the error says to "add a symlink to it from project's node_modules/.", does this not work?
  • TetraDev
    TetraDev almost 6 years
    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.
  • V P
    V P almost 6 years
    @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.
  • its4zahoor
    its4zahoor over 5 years
    Thanks @SurajRao , I moved it here. I hope it's better.
  • Arkady
    Arkady over 5 years
    Not working for me. Getting the same message - 'outside of the project src/ directory. Relative imports outside of src/ are not supported.'
  • Beau Smith
    Beau Smith over 5 years
    This requires first ejecting from create-react-app, no?
  • Dmitry Yudakov
    Dmitry Yudakov about 5 years
    Your answer is correct IMO but I took the liberty of clarifying that you're talking about the path in <img src="...">, not importing it
  • ivosh
    ivosh about 5 years
    Great answer. You can leverage further react-app-rewired with [github.com/arackaf/customize-cra](customize-cra). Then the config will use just babelInclude([path.resolve('src'), path.resolve('../common')]) and removeModuleScopePlugin().
  • its4zahoor
    its4zahoor about 5 years
    @PattycakeJr Yes, that's why below I have told to be ware of eject consequences.
  • rotimi-best
    rotimi-best about 5 years
    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
  • Flaom
    Flaom about 5 years
    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.
  • Si8
    Si8 almost 5 years
    How about for .css file? how would that work with import?
  • Amos Long
    Amos Long almost 5 years
    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
    Amos Long almost 5 years
    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 <img src="/images/logo.png" alt="Logo" />
  • bijayshrestha
    bijayshrestha over 4 years
    can you please confirm where should i place this code snippet?
  • Lukas Bach
    Lukas Bach over 4 years
    @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.
  • adi518
    adi518 over 4 years
    @Flaom That doesn't work anymore (if it actually used to work). You also get a deprecation warning for this variable.
  • adi518
    adi518 over 4 years
    That's the best solution thus far.
  • bluenote10
    bluenote10 about 4 years
    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.
  • Flaom
    Flaom about 4 years
    @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/..
  • Roman Podlinov
    Roman Podlinov about 4 years
    Vote for the craco! Craco supports CRA 3.x
  • oklas
    oklas almost 4 years
    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
  • Admin
    Admin almost 4 years
    Does this solution work with Typescript? I cannot get it working with TS.
  • Lukas Bach
    Lukas Bach almost 4 years
    @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.
  • Yashwin Munsadwala
    Yashwin Munsadwala over 3 years
    @Arkady you might still have an import statement to your photo. Remove that import statement and just give direct path in the src attribute.
  • goldenmaza
    goldenmaza over 3 years
    @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...
  • oklas
    oklas over 3 years
    @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.
  • goldenmaza
    goldenmaza over 3 years
    @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...
  • oklas
    oklas over 3 years
    When two modules will be dependent on the eachother you can configure src from both as alias and import anything from both using alias.
  • Nabil Freeman
    Nabil Freeman over 3 years
    @oklas can you explain why it's not a bad idea? After some digging into an old CRA issue 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.
  • MikeW
    MikeW over 3 years
    works beautifully in conjunction with this stackoverflow.com/a/58603207/2987400
  • oklas
    oklas over 3 years
    @NabilFreeman the reasons to restrict not wanted files by security and performance mentioned in answer 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.
  • Clifford Fajardo
    Clifford Fajardo over 3 years
    The downside of modifying node_modules is that if you do a clean install (pull a fresh copy from github) and then install, your commented out code will be overwritten
  • Mitchell Tracy
    Mitchell Tracy about 3 years
    To get it to work with TypeScript I needed this answer and the link MikeW posted.
  • Katie Fedoseeva
    Katie Fedoseeva about 3 years
    or you know, just moving your files inside the src directory as React intended might be a more obvious solution
  • Abhishek Iyengar
    Abhishek Iyengar almost 3 years
    This saved my day! This should be the accepted answer if you're using something akin to reactron!
  • panepeter
    panepeter almost 3 years
    Added a copy&past answer for Typescript users
  • panepeter
    panepeter almost 3 years
    Took this answer and combined it with this gitlab comment to get it working on Typescript. Full solution as own answer.
  • Avi Nerenberg
    Avi Nerenberg almost 3 years
    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
    Avi Nerenberg almost 3 years
    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
  • herodrigues
    herodrigues almost 3 years
    This should be marked as the correct answer (if you don't want to run the eject command)!
  • David Jones
    David Jones over 2 years
    Works perfectly!
  • cigien
    cigien over 2 years
    Could you add some additional information in your own words as to why the quoted comment addresses the OPs question?
  • Ndrslmpk
    Ndrslmpk over 2 years
    Is it possible to just remove the module and its references if I already uninstalled create-react-app from my project?
  • fullStackChris
    fullStackChris over 2 years
    @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...
  • Urmzd
    Urmzd over 2 years
    @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.
  • fullStackChris
    fullStackChris over 2 years
    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
  • TOPKAT
    TOPKAT about 2 years
    Hi, What if I am working with typescript? The node_module folder is ignored from build sources...
  • Harikrishnan
    Harikrishnan about 2 years
    This will result in necessary code change for production deployment. Better to use base url as an environment variable.