英文:
React Native - babel.config.js alias not seeing files outside the current working directory
问题
Here's the translated content you requested:
所以,我的项目是一个 monorepo(单一仓库)。其中包含了用于 web 应用程序、移动应用程序等的文件夹。还有一个 common
文件夹,其中包含了所有可重用的组件和工具。
<repo-name>
├── app // 移动应用程序
│ ├── node_modules
│ ├── src
│ │ ├── views
│ │ │ ├── Homepage
│ │ │ │ └── index.tsx
│ │ └── App.tsx
│ ├── babel.config.js
│ ├── tsconfig.json
│ └── ...
├── common
│ ├── utils
│ │ └── format.ts
├── web
│ ├── app
│ │ ├── tsconfig.json
│ │ └── ...
│ ├── landing
│ │ ├── tsconfig.json
│ │ └── ...
App.tsx
大致具有以下内容:
import React from "react"
import Homepage from "views/Homepage"
import { someFunction } from "@common/utils/format"
export default class App extends React.Component<any, any> {
render() {
return <>
<h1>{someFunction("kappa")}</h1>
<Homepage />
</>
}
}
移动应用程序的 tsconfig.json
如下所示:
{
"extends": "@tsconfig/react-native/tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"experimentalDecorators": true,
"useDefineForClassFields": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"paths": {
"@common/*": [
"../common/*",
],
"*": [
"./src/*",
"node_modules",
],
}
}
}
而 babel.config.js
则是这样的:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
"@babel/plugin-transform-flow-strip-types",
{ legacy: true },
],
[
"@babel/plugin-proposal-decorators",
{ legacy: true },
],
[
"@babel/plugin-proposal-class-properties",
{ "loose": false }
],
[
'module-resolver',
{
root: ['./src'],
extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
alias: {
"@common": "../common",
}
}
]
]
};
基本上,发生了什么情况。我为 common
文件夹的内容创建了别名,可以通过 @common/...
导入。此外,可以在不使用相对路径的情况下导入 src
文件夹中的所有内容。
这些别名在 tsconfig.json
和 babel.config.json
中都进行了配置。我使用的是 VSCode,在 @common
别名的自动完成方面运行良好。
但是在运行时(在 Metro CLI 中),我遇到了以下错误:
Error: 从 /home/<username>/projects/<project>/<repo-name>/app/src/App.tsx 无法解析模块 ../../common/utils/format:
这些文件均不存在:
* ../common/utils/format(.native|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx)
* ../common/utils/format/index(.native|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx)
如您所见,@common
的路径被完美解析,但出于某种原因,Babel 却看不到 format.ts
文件。
我做错了什么?是否有任何注意事项或解决方法?非常感谢您的帮助。我在这个问题上已经花了大约 4 小时,但没有找到有用的信息。提前感谢。
英文:
So, my project is monorepo. There are folders for web application, mobile application, etc. And there is also a common
folder, where gathered all the reusable components and utils.
<repo-name>
├── app // mobile app
│ ├── node_modules
│ ├── src
│ │ ├── views
│ │ │ ├── Homepage
│ │ │ │ └── index.tsx
│ │ └── App.tsx
│ ├── babel.config.js
│ ├── tsconfig.json
│ └── ...
├── common
│ ├── utils
│ │ └── format.ts
├── web
│ ├── app
│ │ ├── tsconfig.json
│ │ └── ...
│ ├── landing
│ │ ├── tsconfig.json
│ │ └── ...
App.tsx
has schematically the next content:
import React from "react"
import Homepage from "views/Homepage"
import { someFunction } from "@common/utils/format"
export default
class App
extends React.Component<any, any> {
render() {
return <>
<h1>{someFunction("kappa")}</h1>
<Homepage />
<>
}
}
Mobile app's tsconfig.json
looks like this:
{
"extends": "@tsconfig/react-native/tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"experimentalDecorators": true,
"useDefineForClassFields": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"paths": {
"@common/*": [
"../common/*",
],
"*": [
"./src/*",
"node_modules",
],
}
},
}
and the babel.config.js
is this:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
"@babel/plugin-transform-flow-strip-types",
{ legacy: true },
],
[
"@babel/plugin-proposal-decorators",
{ legacy: true },
],
[
"@babel/plugin-proposal-class-properties",
{ "loose": false }
],
[
'module-resolver',
{
root: ['./src'],
extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
alias: {
"@common": "../common",
}
}
]
]
};
Basically, what's going on.
I've created alias for common
folder content to be imported as @common/...
Also, all content from src
folder can be imported without relative paths.
This aliases are configured in both tsconfig.json
and babel.config.json
. I'm using VSCode, and autocomplete for @common
alias works flawlessly.
But in runtime (inside Metro CLI) I'm getting this error:
Error: Unable to resolve module ../../common/utils/format from /home/<username>/projects/<project>/<repo-name>/app/src/App.tsx:
None of these files exist:
* ../common/utils/format(.native|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
* ../common/utils/format/index(.native|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
As you can see, path for @common
is resolved perfectly, but for some reason babel does not see format.ts
file.
What I'm doing wrong? Is there any caveats, any workarounds?
Any help appreciated. Spent abount 4 hours on this problem and found nothing useful.
Thanks in advance
答案1
得分: 1
Okay, so, basically, this is not a problem of the Babel.
Turns out that Metro does not know a thing about folders outside the project.
Well, all you need is to add watchFolders
property to metro.config.js
:
/**
* Metro configuration for React Native
* https://github.com/facebook/react-native
*
* @format
*/
const path = require("path")
module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
// here we should set folders outside of the project folder
// to be able to import modules from 'em
watchFolders: [
path.resolve(__dirname + "/../common")
]
};
Two days searching and the solution is, as always, just 4 rows
The beautiful world of javascript bundlers.
That's all folks!
¯\_(ツ)_/¯
英文:
Okay, so, basically, this is not a problem of the Babel.
Turns out that Metro does not know a thing about folders outside the project.
Well, all you need is to add watchFolders
property to metro.config.js
:
/**
* Metro configuration for React Native
* https://github.com/facebook/react-native
*
* @format
*/
const path = require("path")
module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
// here we should set folders outside of the project folder
// to be able to import modules from 'em
watchFolders: [
path.resolve(__dirname + "/../common")
]
};
Two days searching and the solution is, as always, just 4 rows
The beautiful world of javascript bundlers.
That's all folks!
¯\_(ツ)_/¯
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论