Comment éviter les importations avec des chemins relatifs très longs dans Angular 2?

95

Comment puis-je introduire quelque chose comme 'my-app-name/services'pour éviter les lignes comme l'importation suivante?

import {XyService} from '../../../services/validation/xy.service';
Thomas Zuberbuehler
la source

Réponses:

138

TypeScript 2.0+

Dans TypeScript 2.0, vous pouvez ajouter une baseUrlpropriété dans tsconfig.json:

{
    "compilerOptions": {
        "baseUrl": "."
        // etc...
    },
    // etc...
}

Ensuite, vous pouvez tout importer comme si vous étiez dans le répertoire de base:

import {XyService} from "services/validation/xy.service";

En plus de cela, vous pouvez ajouter une pathspropriété, qui vous permet de faire correspondre un modèle puis de le mapper. Par exemple:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "services/*": [
                "services/validation/*"
            ]
        }
        // etc...
    },
    // etc...
}

Ce qui vous permettrait de l'importer de n'importe où comme ceci:

import {XyService} from "services/xy.service";

À partir de là, vous devrez configurer le chargeur de module que vous utilisez pour prendre également en charge ces noms d'importation. À l'heure actuelle, le compilateur TypeScript ne semble pas les mapper automatiquement.

Vous pouvez en savoir plus à ce sujet dans le numéro de github . Il existe également une rootDirspropriété qui est utile lors de l'utilisation de plusieurs projets.

Pre TypeScript 2.0 (toujours applicable dans TS 2.0+)

J'ai trouvé que cela pouvait être rendu plus facile en utilisant des "barils" .

  1. Dans chaque dossier, créez un index.tsfichier.
  2. Dans ces fichiers, réexportez chaque fichier dans le dossier.

Exemple

Dans votre cas, créez d'abord un fichier appelé my-app-name/services/validation/index.ts. Dans ce fichier, ayez le code:

export * from "./xy.service";

Ensuite, créez un fichier appelé my-app-name/services/index.tset obtenez ce code:

export * from "./validation";

Vous pouvez maintenant utiliser votre service comme ceci ( indexc'est implicite):

import {XyService} from "../../../services";

Et une fois que vous avez plusieurs fichiers, cela devient encore plus facile:

import {XyService, MyOtherService, MyOtherSerivce2} from "../../../services";

Avoir à maintenir ces fichiers supplémentaires est un peu plus de travail au départ (le travail peut être éliminé en utilisant le mainteneur de baril ), mais j'ai trouvé que cela payait à la fin avec moins de travail. Il est beaucoup plus facile de faire des changements majeurs dans la structure des répertoires et cela réduit le nombre d'importations que vous devez effectuer.

Mise en garde

En faisant cela, il y a certaines choses que vous devez surveiller et que vous ne pouvez pas faire:

  1. Il faut surveiller les réexportations circulaires. Donc, si les fichiers de deux sous-dossiers se référencent, vous devrez utiliser le chemin complet.
  2. Vous ne devriez pas revenir en arrière dans un dossier du même dossier d'origine (ex. Être dans un fichier dans le dossier de validation et faire import {XyService} from "../validation";). J'ai trouvé cela et le premier point peut conduire à des erreurs d'importations non définies.
  3. Enfin, vous ne pouvez pas avoir deux exportations dans un sous-dossier portant le même nom. Ce n'est généralement pas un problème.
David Sherret
la source
2
@ ThomasZuberbühler Je pense que dans TypeScript 1.8 qui sera disponible ( voir ici ).
David Sherret
3
Comment puis-je télécharger Typescript 2.0+ avec npm?
maximedupre
4
Un petit conseil - après avoir lu la documentation, il s'est avéré que le baseUrlest relatif à l'emplacement de 'tsconfig.json'. Donc, dans notre cas (application angulaire), la valeur devait être "baseUrl": "./app",, où "app" est la racine de l'application.
Pawel Gorczynski
10
Utilisateurs angular-cli uniquement : si vous utilisez angular-cli 2+, ils sont passés à webpack et à webpack.config.js en boîte noire (à l'intérieur de node_modules). «À partir de là, vous devrez configurer le chargeur de module que vous utilisez pour prendre également en charge ces noms d'importation.» Puisque webpack.config.js est en boîte noire, vous ne pouvez pas faire cette pièce. Heureusement, j'ai trouvé que le problème était déjà signalé ici et résolu par ce PR. TL; DR, la configuration du webpack en boîte noire est suffisamment intelligente pour regarder maintenant tsconfig.json.
Kevin le
1
pour les utilisateurs angular-cli, vous pouvez générer un webpack.config avec "ng eject". Notez que vous devrez supprimer le projet éjecté: true de .angular-cli.json -> afin de pouvoir servir le projet.
Drusantia
14

Mieux vaut utiliser la configuration ci-dessous dans tsconfig.json

{
  "compilerOptions": {
    "...": "reduced for brevity",

    "baseUrl": "src",
    "paths": {
      "@app/*": ["app/*"]
    }
  }
}

Façon traditionnelle avant Angular 6:

`import {XyService} from '../../../services/validation/xy.service';`

devrait être refactorisé en ces:

import {XyService} from '@app/services/validation/xy.service

Court et doux!

Shivang Gupta
la source
ce changement ne fonctionne pas en production @shivangGupta
anonyme
1

Je viens de tomber sur cette question. Je sais qu'il y a longtemps, mais pour quiconque y rencontre, il y a une réponse plus simple.

Je suis tombé sur seulement parce que quelque chose que je faisais depuis longtemps a cessé de fonctionner et je me demandais si quelque chose avait changé dans Angular 7. Non, c'était juste mon propre code.

Quoi qu'il en soit, je n'ai eu qu'à changer une ligne tsconfig.jsonpour éviter les longs chemins d'importation.

{
  "compilerOptions": {
  "...": "simplified for brevity",

   "baseUrl": "src"
  }
}

Exemple:

// before:
import {XyService} from '../../../services/validation/xy.service';

// after:
import { XyService } from 'app/services/validation/xy.service';

Cela a fonctionné pour moi à peu près depuis l'arrivée d'Angular-CLI.

Chris Curnow
la source
Merci pour l'effort Chris, mais vous devriez avoir fourni des exemples d'utilisation dans votre réponse!
George43g