如何在 React Native 中为项目根目录之外的文件夹使用路径别名?

Bjo*_* B. 4 typescript tsconfig babeljs react-native metro-bundler

我正在开发一个 React Native 项目,该项目是具有多个包的更广泛项目的一部分。项目的文件夹结构如下(排除大部分无关文件):

\n
monorepo\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 packages\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 backend\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 frontend-app\n    \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 babel.config.js\n    \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 metro.config.js\n    \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n    \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.js\n    \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 shared\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 data-types.ts\n
Run Code Online (Sandbox Code Playgroud)\n

在文件夹内frontend-app,我希望能够从data-types.ts文件导入类型。@shared/data-types此外,我想通过使用而不是必须使用相对路径../../shared/data-types(甚至更多文件夹)来做到这一点。

\n

我只能发现您必须更新应用程序项目本身内的常规路径babel.config.js别名tsconfig.json,但在运行应用程序时我仍然收到如下警告:

\n
Unable to resolve module ../../../../shared/data-types from ***: \n\nNone of these files exist:\n  * ../shared/data-types(.native|.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx)\n  * ../shared/data-types/index(.native|.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx)\n\n[...]\n\n
Run Code Online (Sandbox Code Playgroud)\n

如何使其适用于 React Native 项目文件夹之外的文件?

\n

Bjo*_* B. 5

路径别名对于更干净的导入和避免大型项目中的相对路径地狱非常有用。虽然它们通常在项目中使用,但有时需要在 React Native 项目根目录之外使用别名路径,特别是在 monorepos 中或在多个项目之间共享代码时。

要使路径别名适用于 React Native 应用程序项目根目录之外的文件/文件夹,您必须修改babel.config.jstsconfig.jsonmetro.config.js文件。

给定你的 React Native 项目和文件夹是同级目录(即它们具有相同的父目录)的目录结构shared,以下是设置路径别名的方法:

1. 安装所需的依赖项: 首先,您需要向 React Native 项目添加开发依赖项,以帮助 Babel 解析别名。

使用 npm:

npm install --save-dev babel-plugin-module-resolver
Run Code Online (Sandbox Code Playgroud)

或者使用纱线:

yarn add --dev babel-plugin-module-resolver
Run Code Online (Sandbox Code Playgroud)

2. 配置您的文件:

babel.config.js

module.exports = {
  presets: ["module:metro-react-native-babel-preset"],
  plugins: [
    "react-native-reanimated/plugin",
    [
      "module-resolver",
      {
        extensions: [".ios.js", ".android.js", ".ios.jsx", ".android.jsx", ".js", ".jsx", ".json", ".ts", ".tsx"],
        root: ["."],
        alias: {
          "@shared": "../shared",
        },
      },
    ],
  ],
};
Run Code Online (Sandbox Code Playgroud)

tsconfig.json

{
  "compilerOptions": {
    // Other settings
    "baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
    "paths": {
      "@shared/*": ["../shared/*"]
    },
    // Other settings
  },
  "include": ["./src/*", "../shared/*"]
}
Run Code Online (Sandbox Code Playgroud)

地铁配置.js

const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
const path = require("path");

/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
  watchFolders: [path.resolve(__dirname + "/../shared")],
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);
Run Code Online (Sandbox Code Playgroud)

完成这些更改后,请确保重新启动 Metro 捆绑程序。如果遇到任何问题,重置缓存可以提供帮助npx react-native start --reset-cache

通过这些更改,您将能够从@sharedReact Native 应用程序中的别名无缝导入。

您可以将此附加信息作为原始答案的更新或附言提供。这是一种可能的格式:


更新:

实现上述内容后,我发现虽然在开发、本地构建和存档中一切都运行良好,但尝试在远程计算机(特别是 Azure DevOps 管道)上使用 Fastlane 进行构建时出现了问题。在构建阶段“捆绑 React Native 代码和图像”期间出现错误,导致 Fastlane 退出代码 65。日志中的底层错误xcodebuild指出:“无法解析包内的模块 @babel/runtime/helpers/interopRequireDefault shared” 。此错误暗示node_modules无法在共享包中找到该文件。

值得庆幸的是,我偶然发现了这个StackOverflow 答案,它提供了一个解决方案。该解决方案的要点是更新metro.config.js. 请注意,这个解决方案可能不是每个人都需要的,但它解决了我的具体问题。

const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
const path = require("path");

/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const extraNodeModules = {
  shared: path.resolve(__dirname + "/../shared"),
};

const watchFolders = [path.resolve(__dirname + "/../shared")];

const nodeModulesPaths = [path.resolve(path.join(__dirname, "./node_modules"))];

const config = {
  resolver: {
    extraNodeModules,
    nodeModulesPaths,
  },
  watchFolders,
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);
Run Code Online (Sandbox Code Playgroud)