【问题标题】:Absolute Imports: React and Typescript绝对导入:React 和 Typescript
【发布时间】:2020-07-28 09:16:29
【问题描述】:

背景

我有一个使用 create-react-app 和 typescript 引导的 React 应用程序。随着应用程序的增长,(目标)我想实现绝对导入。我正在使用 VS Code (Visual Studio Code),只需很少的配置,就可以让 TS 和 VS Code 识别我的绝对导入。

对于 TS,我在tsconfig.json 中采取了以下步骤:

  • 将“baseUrl”更改为“客户端”:"baseUrl": "client"
  • 将“客户”添加到我的include 密钥:"include": ["./**/*.ts", "./**/*.tsx", "client"]

对于 VS Code,我更改了用户设置:Typescript -> Preferences: Import Module Specifier -> non-relative

效果很好。我所有的导入都使用绝对导入,没有错误。但是,当我运行应用程序时,我收到一个错误:Error: Cannot find module "component" 我希望看到我的应用程序,就像我在绝对导入之前所做的那样。

我尝试了什么

想通了,错误是 webpack 或 babel 问题。

  1. 已创建env 文件

    将以下内容添加到应用根目录中的 env 文件(与我的 package.json 相同的位置)

NODE_PATH=client/

那没有用。同样的错误:Error: Cannot find module "components"。还尝试将 NODE_PATH 更改为 REACT_APP_NODE_PATH 也不起作用。

  1. 修改 Babel 配置

    添加了带有yarn add -D babel-plugin-module-resolver 的 babel 插件模块解析器。然后将我的babel.config.js修改为:

module.exports = { 
  env {...}, 
  plugins: [
    [
      'module-resolver',
      {
        cwd: 'babelrc',
        extensions: ['.ts', '.tsx', '.js'],
        alias: {
          client: './client',
        },
      },
    ],
  ]
}

返回相同的错误。 (每次更改配置文件后,我都会重新启动服务器)

引用的资源 我使用了很多不同的文章来试图弄清楚。以下是一些:

  • Kyle Truong (here) 使用 Create React App 实现绝对导入
  • Michael Bednarz (here) 在 Create React App 中的绝对导入
  • Justin Noel (here) 为 TypeScript 配置 React 绝对导入
  • 在 React 组件中使用绝对路径 (StackOverflow)
  • 如何在 React 应用程序的 typescript 文件中导入 js 模块(带绝对路径)?

还有很多其他的。这些都没有奏效。

项目结构

我的项目结构有点“非传统”或不是我的典型模式,这可能会导致问题。

└── root dir
    ├── assets
    │   └── client
    │       ├── assets
    │       ├── components
    │       ├── hooks
    │       └── ...
    │   └── babel.config.js
    │   └── .babelrc
    │   └── webpack.config.js
    │   └── package.json
    └── server files (no server dir) 

所以client 就像我在典型的反应应用程序中的srcassets 是我的服务器的“入口目录”,位于 root dir 中。

任何帮助将不胜感激。

【问题讨论】:

    标签: reactjs typescript webpack babeljs


    【解决方案1】:

    TypeScript 的 React 绝对导入
    以下是它的工作原理。将您的 tsconfig.json 文件修改为如下所示:

       {
          "compilerOptions": {
            ...
            "baseUrl": "src"
          },
          "include": ["src"]
        }
    

    【讨论】:

      【解决方案2】:

      我的解决方案是使用 babel-plugin-module-resolver。为什么?因为它允许我这样做。

      import Comp1 from 'components/comp1';
      import AnotherAppComp from '@app/anotherComp';
      

      它的配置更加灵活,允许别名,或者直接访问。

      babel.config.js中,添加这个插件:

      plugins: [
      [
        require.resolve('babel-plugin-module-resolver'),
        {
          cwd: 'babelrc',
          extensions: [
            '.js',
            '.jsx',
            '.ts',
            '.tsx',
            '.android.js',
            '.android.tsx',
            '.ios.js',
            '.ios.tsx',
          ],
          root: ['.'],
          alias: {
            '@app': './another-app',  // path to your app folder
          },
        },
      ],
      ...
      ]
      

      然后在tsconfig.json中,将compilerOptions改为:

      "compilerOptions": {
      ...
          "baseUrl": ".",                           /* Base directory to resolve non-absolute module names. */
          "paths": {
            "@app/*": ["./another-app/*"],
            "*": ["./src/*"],
          },
      ...
        }
      

      我必须重新启动我的 vscode 才能让它第一次工作。之后,当我编辑时,我不必再重新启动了。

      【讨论】:

        【解决方案3】:

        找到答案。不需要env 文件。只需要修改tsconfig.jsonwebpack.config.js文件即可。

        TS 配置

        添加了两个键:baseUrlpaths。将baseUrl 设置为srcclient 目录。 paths 键将包含一个对象,其中包含您要在绝对路径中引用的任何内容。

        {
          "compilerOptions": {
            ...
            "baseUrl": "./client",
            "paths": {
              "client/*": ["./client/*"]
            },
            ...
          },
          "include": ["./**/*.ts", "./**/*.tsx"]
        }
        

        Webpack 配置

        为“src”添加了一个别名(在我的例子中是“client”)。

        module.exports = (env, options) => ({
          ...
          resolve: {
            alias: {
              client: path.resolve(__dirname, 'client/') // added this
            },
            extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
          }
        })
        

        用法 现在要导入一些东西,我可以用“客户端”替换相对导入。 这个:

        import TableHeader from '../../../components/Table/TableHeader'
        

        变成这样:

        import TableHeader from 'client/components/Table/TableHeader'
        

        如果有更好的方法,请发布您的解决方案。 ?

        【讨论】:

        • 无论我做什么,我都无法让它工作:(我不确定 babel 是否会妨碍我
        猜你喜欢
        • 2019-03-30
        • 2020-04-20
        • 1970-01-01
        • 2021-11-13
        • 2019-06-28
        • 2021-06-28
        • 2020-10-18
        • 1970-01-01
        • 2022-01-09
        相关资源
        最近更新 更多