【问题标题】:How to set alias path via webpack in CRA (create-react-app) and craco?如何在 CRA(create-react-app)和 craco 中通过 webpack 设置别名路径?
【发布时间】:2019-10-16 16:13:58
【问题描述】:

我在使用 create-react-appcraco 设置 webpack 别名路径时遇到问题,我已经在谷歌上搜索过但无法解决问题。

每次我使用命令yarn start 运行应用程序时都会收到错误Module not found: Can't resolve '@app/App' in 'C:\ReactSandbox\my-project\src

重现步骤:

  1. create-react-app my-project
  2. cd my-project
  3. yarn add @craco/craco
  4. cat > craco.config.js (见下面的配置)
  5. 将 package.json 上“脚本”部分的 react-scripts 替换为 craco(craco start、craco build 等)
  6. 编辑文件src/index.js (替换第4行,见下面的代码)
  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();

当前结果

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

预期

我避免调用相对路径地狱,而不是像../../../../FilterComment.js 这样的导入模块,写@app/FilterComment.js 会很干净

【问题讨论】:

    标签: javascript reactjs webpack


    【解决方案1】:

    我正在使用craco-alias 插件为 Webpack 和 Jest 自动生成别名。 (我只是一名实习生,但这就是我公司的高级开发人员在 react 中使用绝对导入的方式)

    安装

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

    并确保 package.json 中的脚本如下所示

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

    然后它将按照 tsconfig.json 中指定的方式工作。

    仅供参考, "react-scripts": "4.0.3" "@craco/craco": "^6.3.0" "craco-alias": "^3.0.1"

    【讨论】:

      【解决方案2】:

      一个不使用依赖的例子(我正在使用):

      //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": {/*...*/}
      }
      
      

      【讨论】:

        【解决方案3】:

        我的 craco.config.js 如下所示,它可以工作:

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

        【讨论】:

        • craco 不需要弹出。我使用相同的 craco.config.js 别名设置但没有 path.join 并且它工作正常
        • 是的,不需要将path.resolve 的结果包装在path.join
        • 如果我们有具有范围的节点包,这将如何工作......比如@sentry/react等......
        【解决方案4】:

        也许 OP 有不同版本的 React / Webpack(我正在使用今天的当前版本),但是将 alias 对象直接放在 webpack 对象中(没有将其嵌套在 resolve 对象中)确实我的诀窍:

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

        【讨论】:

          【解决方案5】:

          解决carco:

          你需要安装craco-alias,然后会写入 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"
                ]
              }
          
          

          【讨论】:

          • 这是正确的。赞成。终于解决了我的问题..谢谢
          • 如何使用示例? import myhooks from @hooks/hooks.tsx?
          【解决方案6】:

          首先 - 告诉 IDE tsconfig.json 中的别名:

          创建单独的文件tsconfig.paths.json 并添加别名:

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

          将创建的tsconfig.paths.json 添加到主tsconfig.json

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

          第二个 - 告诉 webpack 别名:

          config-overrides.js添加别名

          const {
             override,
             addWebpackAlias
          } = require('customize-cra');
          
          const path = require("path");
          
          module.exports = override(
             addWebpackAlias({
                "@utils": path.resolve(__dirname, "./src/utils"),
             }),
          );
          

          【讨论】:

            【解决方案7】:

            使用react-app-rewire-alias

            // config-overrides.js:
            
            const {alias} = require('react-app-rewire-alias')
            
            module.exports = function override(config) {
              alias({
                "@app": "src",
              })(config)
              return config
            }
            

            或将 jsconfig.jsonconfigPaths() 一起使用

            typescript 的配置需要一些额外的步骤,检查docs

            现在你可以导入了:

               import App from '@app/App'
            

            【讨论】:

              【解决方案8】:

              只需像这样保留您的文件craco.config.js,然后您需要再添加1个名为jsconfig.json的文件

              内容:

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

              然后你可以从@app/FilterComment.js这样的绝对路径导入

              它也适用于 VSCode(编辑器现在了解 @app 指向的位置)。 但是如果你想让 VSCode 自动进行导入,那么你应该为它添加更多的配置来强制它总是从绝对路径导入。

              文件.vscode/settings.json 内容:

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

              【讨论】:

              • react 脚本不允许您将“路径”放入 tsconfig.json,它会自动为您删除
              • 为了防止 react-script 脚本从 tsconfig.json 中删除 paths,创建 tsconfig.path.json(例如) ,添加paths设置并在tsconfig.json中扩展
              猜你喜欢
              • 2019-11-25
              • 2020-05-21
              • 1970-01-01
              • 1970-01-01
              • 2018-03-14
              • 2020-12-09
              • 1970-01-01
              • 2021-08-19
              • 2019-02-07
              相关资源
              最近更新 更多