11

I have a problem on set webpack alias path using create-react-app and craco, already googling it but can't solve the problem.

I got an error Module not found: Can't resolve '@app/App' in 'C:\ReactSandbox\my-project\src everytime i run application using command yarn start

Steps to reproduce:

  1. create-react-app my-project
  2. cd my-project
  3. yarn add @craco/craco
  4. cat > craco.config.js (see configuration below)
  5. replace react-scripts to craco on 'script' section on package.json (craco start, craco build, etc)
  6. edit file src/index.js (replace line 4, see code below)
  7. yarn start

craco.config.js

const path = require("path");

module.exports = {
  webpack: {
    resolve: { 
      alias: {
        "@app": path.resolve(__dirname, "src/"),
      }
    }    
  }
};

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from '@app/App'; //replace './App' into '@app/App'
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));

serviceWorker.unregister();

Current result

Module not found: Can't resolve '@app/App' in 'C:\ReactSandbox\my-project\src

Expected

I'm avoiding call relative path hell, instead of import module like ../../../../FilterComment.js, it would be clean to write @app/FilterComment.js

1
  • Removing the "resolve: { }" worked for me. Commented Jun 29, 2022 at 21:59

8 Answers 8

12

resolve for carco:

u need install craco-alias, then will write in craco.config.js

    const CracoAlias = require('craco-alias')

    module.exports = {
      plugins: [
        {
          plugin: CracoAlias,
          options: {
            source: 'tsconfig',
            baseUrl: '.',
            tsConfigPath: './tsconfig.path.json',
          },
        },
      ],
    }

tsconfig.path.json

    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/*": ["src/*"],
          "@svg/*": ["src/assets/svg/*"],
          "@img/*": ["src/assets/images/*"],
          "@icons/*": ["src/assets/icons/*"],
          "@shared/*": ["src/shared/*"],
          "@components/*": ["src/components/*"],
          "@hooks/*": ["src/hooks/*"],
          "@constants/*": ["src/constants/*"],
          "@layout/*": ["src/layout/*"],
          "@services/*": ["src/services/*"]
        }
      }
    }

tsconfig.json

    {
      "extends": "./tsconfig.path.json",
      "compilerOptions": {
        "target": "es5",
        "lib": [
          "dom",
          "dom.iterable",
          "esnext"
        ],
        "allowJs": true,
        "checkJs": false,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "declaration": false,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "noEmit": true,
        "jsx": "react-jsx",
        "noFallthroughCasesInSwitch": true,
        "removeComments": true
      },
      "include": [
        "src",
        "src/configs",
        "react-app-env.d.ts"
      ]
    }

Sign up to request clarification or add additional context in comments.

2 Comments

this is correct. upvoted. solved my problem atlast.. thankiiies
Example of how to use? import myhooks from @hooks/hooks.tsx?
7

First - tell to IDE about aliases in tsconfig.json:

create separate file tsconfig.paths.json and add aliases:

{
   "compilerOptions": {
      "baseUrl": "./src",
      "paths": {
         "@utils/*": ["utils/*"]
      }
   }
}

Add created tsconfig.paths.json to main tsconfig.json

{
   "extends": "./tsconfig.paths.json",
   ... other staff ...
}

Second - tell to webpack about aliases:

Add aliases to config-overrides.js

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

const path = require("path");

module.exports = override(
   addWebpackAlias({
      "@utils": path.resolve(__dirname, "./src/utils"),
   }),
);

Comments

6

my craco.config.js look likes below, it works:

const path = require('path');

module.exports = {
    // ...
    webpack: {
        alias: {
            '@': path.join(path.resolve(__dirname, './src')),
        }
    }
}

4 Comments

No eject is needed with craco. I use the same craco.config.js alias setting but without path.join and it works fine
Yeah, no need to wrap results of path.resolve in path.join
how would this work for the case if we have node package with scope.. like @sentry/react etc...
@MurtazaHussain As per some nodejs docs somewhere, they suggest using # instead of @ which is what I do... it's a bit weird but it works... and node said to do so. I feel like there was a more explicit suggestion for it but here it is implicitly. This avoids the clash with @
2

Just keep your file craco.config.js just like this, and you need to add 1 more file with named jsconfig.json

it's content:

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2016",
    "jsx": "preserve",
    "checkJs": true,
    "baseUrl": "./src/",
    "paths": {
      "@app/*": ["./*"]
    }
  },
  "exclude": ["node_modules", "**/node_modules/*"]
}

then you can import from the absolute path like @app/FilterComment.js

It also worked for VSCode (editor now understand where @app point to). But if you want VSCode to do the import automatically, then you should add more config for it to force it always do the import from absolute path.

file .vscode/settings.json content:

{
  "javascript.preferences.importModuleSpecifier": "non-relative"
}

2 Comments

react script does not allow you put "paths" in tsconfig.json, it remove automatically for you
To prevent the react-script script from removing the paths from tsconfig.json, create tsconfig.path.json (for example), add the paths settings and extend in tsconfig.json
1

Maybe the OP had a different version of React / Webpack (I'm using today's current versions), but putting the alias object directly inside the webpack object (without nesting it in the resolve object) did the trick for me:

const path = require("path");

module.exports = {
  webpack: {
    alias: {
      "@app": path.resolve(__dirname, "src"),
    }
  }
};

Comments

1

An example (which I'm using) without using dependency:

//craco.config.js
const path = require('path')

const tsconfig = require('./tsconfig.base.json')

const removeAsterisk = path => path.replace('/*', '')

const aliasProps = Object.entries(tsconfig.compilerOptions.paths).map(([key, value]) => {
  const newKey = removeAsterisk(key)
  let newValue = removeAsterisk(value[0])
  newValue = path.resolve(__dirname, newValue)
  return [newKey, newValue]
})

const alias = Object.fromEntries(aliasProps)

module.exports = {
  webpack: {
    alias,
  },
}

//tsconfig.base.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "~/*": ["./src/*"],
      //...
    }
  }
}

// tsconfig.json
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {/*...*/}
}

Comments

1

Use react-app-alias:

  • Install craco and react-app-alias and create craco config:
// craco.config.js
const {CracoAliasPlugin} = require('react-app-alias')

module.exports = {
  plugins: [
    {
      plugin: CracoAliasPlugin,
      options: {}
    }
  ]
}

Replace react-scripts with craco in package.json.

Create typescript config and alias in separated config like this:

// tsconfig.paths.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "example/*": ["example/src/*"],
      "@app/*": ["app/src/*"]
    }
  }
}
// tsconfig.json
{
  "extends": "./tsconfig.paths.json",
  // ...
}

Now you can do import like this:

   import App from '@app/App'

1 Comment

What's the difference between this and your other react-app-rewire-alias? Which one will you be supporting?
0

I am using craco-alias plugin for automatic aliases generation for Webpack and Jest. (I am just an intern but that's how senior developers in my company are using absolute imports in react)

Install

yarn add @craco/craco
yarn add craco-alias

craco.config.js

const CracoAlias = require('craco-alias');

module.exports = {
  plugins: [
    {
      plugin: CracoAlias,
      options: {
        source: 'tsconfig',
        baseUrl: './src',
        tsConfigPath: './tsconfig.paths.json', // or wherever you have defined your paths
      },
    },
  ],
};

And make sure that you scripts in package.json look like the following

"scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "craco eject",
    ...
  },

Then It'll work as specified in tsconfig.json.

FYI I have, "react-scripts": "4.0.3" "@craco/craco": "^6.3.0" "craco-alias": "^3.0.1"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.