Итак, мой проект монорепозиторий. Есть папки для веб-приложений, мобильных приложений и т. д. А еще есть папка common
, где собраны все повторно используемые компоненты и утилиты.
<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
схематически имеет следующее содержание:
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: 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)
Как видите, путь для @common
распознан отлично, но Babel почему-то не видит format.ts
файл.
Что я делаю неправильно? Есть ли какие-либо предостережения, какие-либо обходные пути? Любая помощь приветствуется. Потратил около 4 часов на эту проблему и не нашел ничего полезного. заранее спасибо
Итак, в принципе, это не проблема Вавилона. Оказывается, Metro ничего не знает о папках вне проекта.
Ну, все, что вам нужно, это добавить свойство watchFolders
к 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")
]
};
Два дня поиска и решения как всегда всего 4 строчки
Прекрасный мир сборщиков javascript.
Это все ребята!
¯\_(ツ)_/¯