Avoiding relative paths in Angular CLI

62,125

Solution 1

Per this comment, you can add your application source via paths in tsconfig.json:

{
  "compilerOptions": {
    ...,  
    "baseUrl": ".",
    "paths": {
      ...,
      "@app/*": ["app/*"],
      "@components/*": ["components/*"]
    }
  }
}

Then you can import absolutely from app/ or components/ instead of relative to the current file:

import {TextInputConfiguration} from "@components/configurations";

Note: baseUrl must be specified if paths is.

See also

Solution 2

Thanks to jonrsharpe's answer for pointing me in right direction. Although, after adding the paths, as defined in answer, I was still not able to make it work. For anyone else facing same problem as me in future, here's what I did to fix the issues.

I have a shared module and its services are being used in multiple components, so...

tsconfig.json:

{
    "compilerOptions": {
        ...
        "baseUrl": ".", //had to add this too
        "paths": {
            "@shared/*": ["src/app/modules/shared/*"]
        }
    }
}

After this, VS Code was able to resolve the import but I still got following error from webpack while compilation.

Module not found: Error: Can't resolve

To fix this I had to add

  1. baseUrl of tsconfig in webpack's resolve.modules
  2. paths of tsconfig in webpack's resolve.alias

webpack.config.js:

resolve: {
  extensions: ['*', '.js', '.ts'],
  modules: [
    rootDir,
    path.join(rootDir, 'node_modules')
  ],
  alias: {
    '@shared': 'src/app/modules/shared'
  }
},

component.ts:

import { FooService } from '@shared/services/foo.service'
import { BarService } from '@shared/services/bar.service'
import { BazService } from '@shared/services/baz.service'

To make it even more cleaner, I added an index.d.ts inside services folder and exported all my services from there, like this:

index.d.ts:

export * from './foo.service';
export * from './bar.service';
export * from './baz.service';

and now inside any component:

import { FooService, BarService, BazService } from '@shared/services';

Solution 3

Above all answer correct, but after struggling by searching over internet n trying to understand what exactly problem and trying different troubleshooting option, I came to know baseUrl and Path how works toghether

If you use baseUrl:"." like below it works in VScode but not while compiling

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "baseUrl": ".",
    "paths": {
      "@myproject/*": ["src/app/*"]
    }    
}

As per my understanding and my working app and checked in angular aio code, I suggest use as baseUrl:"src" like below

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "baseUrl": "src",
    "paths": {
      "@myproject/*": ["app/*"],
      "testing/*": ["testing/*"]
    }    
}

By having base url as source(src directory), compiler properly resolves modules.

I hope this helps to people resolve this kind of issue.

Solution 4

Not sure why but when I tried the other answers in VS2017, I was able to compile Angular without errors but I was still seeing errors in VS "Cannot find Module ...". When I set the baseUrl to "src" from "." everyone was happy.

tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "baseUrl": "src",                 // Main source directory same level as tsconfig
    "paths": {
      "app/*": [ "app/*" ],           // src/app
      "ui/*": [ "ui/*" ],             // src/ui       
      "services/*": [ "services/*" ], // src/services
      "assests/*": [ "assests/*" ],     // src/assests
      "models/*": [ "models/*" ]      // src/models
    },
    "lib": [
      "es2017",
      "dom"
    ]
  }
}

Then to import:

import { AppMenuComponent } from 'ui/app-menu/app-menu.component';

Note: If Visual Studio is still throwing errors try either closing and reopening the file or restarting Visual Studio to get it to recognize the new paths.

Solution 5

In Angular 8, no need for the *. The * will cause error of Cannot find module add this to you tsconfig.json file

"baseUrl": "./",
"paths": {
      "@test": [ "src/app/test/" ],
      "@somthing": [ "src/app/something/" ],
      "@name": [ "src/app/name/" ]
    },

Share:
62,125
Pratik Kelwalkar
Author by

Pratik Kelwalkar

Updated on May 17, 2020

Comments

  • Pratik Kelwalkar
    Pratik Kelwalkar about 4 years

    I'm using the latest Angular CLI, and I've created a custom components folder which is a collection of all components.

    For example, TextInputComponent has a TextInputConfiguration class which is placed inside src/components/configurations.ts, and in src/app/home/addnewuser/add.user.component.ts where I use it there is:

    import {TextInputConfiguration} from "../../../components/configurations";
    

    This is fine but as my app gets larger and deeper the ../ increases, how do I handle this?

    Previously, for SystemJS, I would configure the path through system.config.js as below:

    System.config({
    ..
     map : {'ng_custom_widgets':'components' },
     packages : {'ng_custom_widgets':{main:'configurations.ts', defaultExtension: 'ts'},
    )};
    

    How do I produce the same for webpack using Angular CLI?

  • Pratik Kelwalkar
    Pratik Kelwalkar over 7 years
    Awesome! , configured it according to your new answer, sailed through!!
  • Syed Ali Taqi
    Syed Ali Taqi about 7 years
    for anyone else in future, I had to set the option of baseUrl along with the answer to get it work.
  • jonrsharpe
    jonrsharpe about 7 years
    @SyedAliTaqi set it to what?
  • Syed Ali Taqi
    Syed Ali Taqi about 7 years
    @jonrsharpe: to root directory of my app. even after that, VS Code was able to resolve the dependency but Webpack's ts loader was still giving error of unable to resolve module. To fix that, I had to add alias and modules properties in my webpack.config
  • Syed Ali Taqi
    Syed Ali Taqi about 7 years
    yes, I tried with "." but I had to explicitly add baseUrl and paths in webpack config to get it work.
  • Drusantia
    Drusantia almost 7 years
    I spent hours with this and finally gave up. Webpack is buggy. Even if I added the same paths to its resolve, it wouldn't run normally.
  • Blaze
    Blaze over 6 years
    thanks that solved it. Without baseUrl as "src" compiler was trying to resolve with respect to root.
  • Douglas Gaskell
    Douglas Gaskell over 6 years
    Sadly this doesn't seme to work anymore? Using this verbatim, and it still can't seem to figure out the paths.
  • nephiw
    nephiw about 6 years
    I am using Angular CLI - so I don't want to edit the webpack files... this helped me a lot.
  • MartinJH
    MartinJH almost 6 years
    baseUrl set to src worked for me :) Otherwise the other answers were good.
  • Impulse The Fox
    Impulse The Fox about 5 years
    It says error TS2307: Cannot find module '@service/example/example.service'. I've got "baseUrl": "./src/app/" and "paths": {"@serivce/*": ["service/*"]}
  • Stephane
    Stephane almost 5 years
    What if the project is a library ? How to export these paths mappings to the client application ?
  • Stephane
    Stephane almost 5 years
    Did you try with ./ instead of . ?
  • Stephane
    Stephane almost 5 years
    What if your project is a library ? How do you expose these mappings to the client application ?
  • Paul-Sebastian
    Paul-Sebastian about 4 years
    It's kind of pointless to specify the same path component in the key and in the value. The above example can be simplified/reduced as: "@/*": ["src/app/*"] and then you can import from @/components or @/any_other_folder with just that one path mapping. Also, I think you have an error in your config: your paths are relative to ., but angular app folder is in ./src/app not in ./app.
  • Syed Ali Taqi
    Syed Ali Taqi almost 4 years
    @Stephane have a look at this question.
  • Eyeslandic
    Eyeslandic over 3 years
    This works but VS Code doesn't pick up on it and gives a warning/error.
  • Ethan SK
    Ethan SK over 3 years
    remember to 'restart ts server' in command palette in vscode