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.jsyarn 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.