Afin d'éviter les importations relatives de style «../../../../» dans une application React Native basée sur TypeScript, je voudrais configurer l'application afin que je puisse utiliser des importations absolues à la place.
Il est important que la configuration prenne également en charge les tests unitaires Jest.
J'ai créé l'application à l'aide de npx react-native init MyTestApp --template typescript
Version native de React: 0.60.5
Quelle est la configuration exacte dont j'aurais besoin pour y parvenir?
5 Réponses :
Sommaire:
Le package npm babel-plugin-module-resolver
est nécessaire, ainsi qu'une configuration dans tsconfig.json
et babel.config.js
Pas à pas:
npm install babel-plugin-module-resolver
(ou yarn add babel-plugin-module-resolver
)
tsconfig.json
: Ajoutez "baseUrl": "."
à compilerOptions
babel.config.js
: ajoutez une clé nommée plugins
avec la valeur suivante:
module.exports = { presets: ['module:metro-react-native-babel-preset'], plugins: [ [ 'module-resolver', { extensions: [ '.js', '.jsx', '.ts', '.tsx', '.android.js', '.android.tsx', '.ios.js', '.ios.tsx' ], root: ['.'] } ] ] };
Configuration complète:
tsconfig.json
:
{ "compilerOptions": { "allowJs": true, "allowSyntheticDefaultImports": true, "esModuleInterop": true, "isolatedModules": true, "jsx": "react", "lib": ["es6"], "moduleResolution": "node", "noEmit": true, "strict": true, "target": "esnext", "baseUrl": "." }, "exclude": ["node_modules", "babel.config.js", "metro.config.js", "jest.config.js"] }
babel.config.js
:
[ [ 'module-resolver', { extensions: [ '.js', '.jsx', '.ts', '.tsx', '.android.js', '.android.tsx', '.ios.js', '.ios.tsx' ], root: ['.'] } ] ]
Ceci est pour un nouveau projet propre créé à l'aide de npx react-native init MyTestApp --template typescript
sur React Native version 0.60.5
babel-plugin-module-resolver doit être installé dans devDependencies
{ "compilerOptions": { "allowJs": true, "allowSyntheticDefaultImports": true, "esModuleInterop": true, "isolatedModules": true, "jsx": "react", "lib": ["es2015", "es2015.promise", "es2016.array.include", "dom"], "strict": true, "moduleResolution": "node", "baseUrl": "./", "paths": { "@cuteapp/*": ["app/*/index", "app/*"] }, "noEmit": true, "resolveJsonModule": true, "target": "esnext", "types": ["jest"] }, "exclude": ["node_modules", "babel.config.js", "metro.config.js"] }
module.exports = { presets: ['module:metro-react-native-babel-preset'], plugins: [ [ require.resolve('babel-plugin-module-resolver'), { cwd: 'babelrc', extensions: ['.ts', '.tsx', '.js', '.ios.js', '.android.js'], alias: { '@cuteapp': './app' } } ], 'jest-hoist' ] };
babel.config.js
yarn add --dev babel-plugin-module-resolver
tsconfig.json
// Meh import config from '../../../../../../../config'; // Awesome! import config from '@cuteapp/config';
Une petite chose (mais potentiellement déroutante) - c'est babel-config-js
(pas json
)
la clé tsconfig.json
jsx
doit également être react-native
selon la question.
Pour tous ceux qui utilisent TypeScript et souhaitent simplement utiliser l'importation avec des chemins absolus sans alias.
En supposant que tous vos dossiers de code sont à l'intérieur de src
.
Insérez "baseUrl": "src"
dans l'objet compilerOptions
dans tsconfig.json
.
Vous pouvez désormais utiliser des chemins absolus dans les importations.
Cela ne fera que faire fonctionner la vérification de type, cela n'aidera pas à la compilation
Vous pouvez le résoudre en 5 étapes simples sans éjecter :
Étape 1 : Ajout de react-app-rewired dans vos devDependencies
.
yarn add -D react-app-rewired
npm intall react-app-rewired --save-dev
ou npm intall react-app-rewired --save-dev
Étape 2 : Après l'installation, vous pourrez modifier les scripts ReactsJS par défaut de package.json
en:
const path = require('path'); module.exports = function override(config) { config.resolve = { ...config.resolve, alias: { ...config.alias, 'services': path.resolve(__dirname, 'src/shared/services'), 'interfaces': path.resolve(__dirname, 'src/shared/interfaces') }, }; return config; };
Étape 3 : crée un nouveau fichier appelé tsconfig.paths.json
sur le chemin racine, avec un contenu comme:
{ "extends": "./tsconfig.paths.json", ...//rest of file infos compilerOptions, include... whatever }
Astuce 1 : vous pouvez choisir le chemin que vous souhaitez utiliser, comme: @services, @interface, @src, ~, @, etc
en changeant simplement les clés à l'intérieur de "paths": {}
La même chose s'applique à sa valeur: ["src/shared/services/ "], ["src/shared/interfaces/ "], ["src/*"]
, utilisez le chemin relatif ici.
Étape 4 : Dans tsconfig.json
, avant "compilerOptions"
vous devez étendre le tsconfig.paths.json
vous venez de créer.
Comme ça:
{ "compilerOptions": { "baseUrl": ".", "paths": { "services/*": ["./src/shared/services/*"], "interfaces/*": ["./src/shared/interfaces/*"] } } }
Étape 5 : crée un nouveau fichier config-overrides.js
, en y ajoutant votre alias et les chemins relatifs:
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-app-rewired eject" }
Astuce 2 : Si vous utilisez eslint
, n'oubliez pas d'avoir un fichier .eslintignore
et ajoutez config-overrides.js
y config-overrides.js
.
Redémarrez votre IDE ou votre éditeur de texte, dans mon cas VSCode.
C'est fait ! . Maintenant, lancez simplement yarn start
ou npm run start
Toutes les autres réponses n'ont pas fonctionné pour moi avec un projet React Native + Typescript fraîchement créé.
Ce qui a fonctionné pour moi a été de définir à la fois baseUrl
et les paths
dans tsconfig.json
:
{ "baseUrl": ".", "paths": { "NAME_IN_PACKAGE_JSON/*": ["./*"] } }
Remplacez NAME_IN_PACKAGE_JSON par le champ de nom de votre package.json
. Par exemple, si le champ de nom est myapp
vous pouvez faire:
import HomeScreen from "myapp/screens/HomeScreen";
Lorsque j'essaye de définir des "paths"
, j'obtiens ceci au moment de la construction: The following changes are being made to your tsconfig.json file: - compilerOptions.paths must not be set (aliased imports are not supported)
, mais apparemment juste le "baseUrl"
paramètre "baseUrl"
suffit maintenant. Au moins pour moi, cela fonctionne bien.