Imports relatifs VS. imports absolus
Le découpage des applications JavaScript en modules permet d’avoir un code bien structuré qui respecte le principe de SoC (Separation of Concerns).
En revanche à mesure que les projets grossissent, la profondeur des dossiers devient plus importante et il est parfois difficile d’importer un module de manière relative. Concrètement on se retrouve très souvent dans ce genre de situation :
// src/pages/Home/HomeSection1.js
import Button from '../../../components/Button'
Ces imports dits relatifs sont peu lisibles et difficilement maintenables.
Imaginons par exemple que l’on veuille placer le fichier HomeSection1.js dans un sous-dossier : src/pages/Home/components/HomeSection1.js. On se retrouve alors à devoir modifier l’import comme ceci :
// src/pages/Home/components/HomeSection1.js
import Button from '../../../../components/Button'
Pour régler ce problème, il est possible d’utiliser des imports absolus.
Ces derniers permettent d’importer des modules en précisant leur chemin absolu par rapport à un dossier racine, communément le dossier src. En pratique, cela signifie que l’instruction import ‘mon/sous/module’ va importer le module situé dans le fichier src/mon/sous/module.js. De notre exemple, il suffira d’importer nos modules de la façon suivante :
// src/pages/Home/components/HomeSection1.js
import Button from 'components/Button'
Voyons comment configurer ces imports absolus pour des applications React puis React Native.
React
Dans cet article, nous partirons du principe que vous avez créé une application React en utilisant l’outil create-react-app.
Pour configurer les imports absolus dans une application React, il suffit de créer un fichier jsconfig.json à la racine du projet avec ce contenu :
{
"compilerOptions": {
"baseUrl": "src"
}
}
Et ça s’arrête là !
Lors du build de l’application, le fichier jsconfig.json est automatiquement lu et utilisé pour configurer certaines options comme celle-ci. Il est également utilisé par l’éditeur Visual Studio Code pour configurer les projets utilisant du code JavaScript.
Si vous avez éjecté votre application de create-react-app, cette configuration fonctionnera toujours car le script eject génère la configuration Webpack nécessaire.
Si votre application n’a pas été générée avec create-react-app mais que vous utilisez Webpack, vous pouvez utiliser l’option resolve/alias de Webpack dans votre fichier webpack.config.js.
React Native
Dans le cas des applications React Native, le fichier jsconfig.json n’est pas interprété, il faut donc configurer la résolution des modules manuellement.
Pour ce faire, nous allons utiliser le module Babel babel-plugin-module-resolver. Ce module indique à Babel la manière dont les instructions import doivent être résolues.
- Commençons par installer le module :
yarn add --dev babel-plugin-module-resolver
- Il faut ensuite déclarer et configurer le module dans le fichier babel.config.js à la racine du projet. On y précise que les imports absolus seront interprétés comme issus du dossier src :
// babel.config.js
module.exports = {
// ... reste de la configuration
plugins: [
['module-resolver': { root: ['./src'] }]
]
}
- Avant de relancer l’application, il faut vider les différents caches pour être sûr de voir nos modifications prises en compte :
rm -rf ios/build android/app/build
watchman watch-del-all
yarn start --reset-cache
- Les imports absolus sont maintenant configurés !
Pour que l’auto-complétion continue de fonctionner dans votre éditeur favoris, vous devrez aussi créer un fichier jsconfig.json comme celui vu dans la partie sur React.
Pour aller plus loin
Votre application supporte maintenant les imports absolus. Il reste maintenant à remplacer tous les imports relatifs qui nous semblent trop longs ou problématiques par de beaux et simples imports absolus.
Attention toutefois à ne pas en abuser, car cette pratique n’est pas toujours adaptée. Par exemple, utiliser un import absolu pour importer un module qui se trouve dans le même dossier n’apportera aucune valeur ajoutée au niveau de la lisibilité. Chaque équipe a ses bonnes pratiques, mais voici quelques conseils :
Utilisez un import absolu si vous importez un module public et faiblement couplé au module appelant
Utilisez un import relatif si vous importez un module fortement couplé au module appelant (même feature, ou sous-module).
Pour terminer, si vous utilisez ESLint vous devrez le configurer pour qu’il comprenne lui aussi vos imports absolus. Tournez-vous dans ce cas vers le plugin eslint-plugin-import.