9

This seems simple but it doesn't work (for me)

I am running an Angular 5 app that has three files in locations similar to this:

app_directory/tsconfig.json
app_directory/src/app/services/my-service.service.ts
app_directory/src/app/main/sub1/sub2/my-component.component.ts

In the my-component.component.ts file I can successfully import my-service with the following line:

import { MyServiceService } from '../../../services/my-service.service.ts'

While this is all fine and dandy, It's kinda annoying to have to put the relative path every time I want to import this service so I did some checking on SO and I found this post: How to avoid imports with very long relative paths in Angular 2?

So I attempted to do the same thing and changed my tsconfig.json to the following:

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./src/app/",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom"
    ]
  }
}

And changed my import to this:

import { MyServiceService } from 'services/my-service.service.ts'

But of course this didn't work. So (without changing the import) I tried the following values for baseUrl:

.
./
./app
./src
./app/
./src/
src/app
src/app/

It seems as though the tsconfig baseUrl has no effect at all. What am I missing here?

Dallas Caley
  • 5,367
  • 6
  • 40
  • 69
  • have you tried putting an absolute path in? like `C:\Users\folder\app\src\` or `/c/users/folder/app/src`? see if that works first, or try to echo the value of baseUrl see if it looks correct – Sergio Alen Feb 16 '18 at 00:31
  • I hadn't tried it, but i did just now that also does not work. Even if it did work it would be super annoying because this code is deployed on many different servers at different locations in the file structure of each individual machine – Dallas Caley Feb 16 '18 at 16:08

2 Answers2

10

I finally figured it out... So it turns out I was right. My tsconfig file was having literally no effect at all because it wasn't even being used.

Here is how I figured it out.

The way I was serving the site was via the:

npm start

Command. I know from other investigation that this command looks at my package.json and runs whatever command I have in {"scripts":{"start" ...} which for me was:

ng serve --sourcemap --extract-css --host 0.0.0.0 --proxy-config proxy.config.json

Keep in mind that I inherited this code so I have no idea how/why much of it was set up initially. Anyhow, I also know that whenever ng serve is run it looks at a file called .angular-cli.json. This is my angular.cli.json: (or at least the part of it that matters)

{
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico"
      ],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.app.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "styles": [
        "styles.scss"
      ],
      "scripts": [],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts",
        "up-gui-1": "environments/environment.up-gui-1.ts"
      }
    }
  ],
}

See that line that says "tsconfig":"tsconfig.app.json" ?

Yep, that's it. I don't have a file called tsconfig.app.json. Not in the root at least. In the root there is a file called tsconfig.json. So I searched and found a tsconfig.app.json one level down (in the src directory). I changed that file to have this:

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

And i changed my import to this:

import { MyServiceService } from '@services/my-service.service';

And all is good now.

Dallas Caley
  • 5,367
  • 6
  • 40
  • 69
0

The big difference that I can see between what you are doing and what the other answer was doing is that you are not using the paths setup inside of your angular-cli.json file, along with the baseUrl. From what I can tell, they are using this functionality to allow you to "map" a base path, along with any matching subdirectories, to a provided path on the file system. In order to make your code work the way you want it to, this is what you need to do:

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./src/app/",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom"
    ],
    "paths": {
      "services/*": [
        "services/*"
      ],
      "components/*": [
        "main/sub1/sub2/*",
        "main/sub3/sub4/*"
      ]
    }
  }
}

// Then you will be able to do things like this:

import { MyServiceService } from 'services/my-service.service.ts'
import { MyComponentComponent } from 'components/my-component.component.ts'
th3n3wguy
  • 3,649
  • 2
  • 23
  • 30
  • I did mess around with the paths value after my initial post but I hadn't tried exactly what you have here. I tried it just now though and it does not work. I'm a bit confused by the nomenclature. Why would I put 'services/*' as a parent of 'services/*' when there is only one folder called services? – Dallas Caley Feb 16 '18 at 16:09
  • 1
    @DallasCaley => The only reason I did this was so that you could potentially split up your "services" into multiple paths that weren't necessarily located within the `/services/*` directory. Hence, the reason I showed the example I did with the extra paths under the "components" section. – th3n3wguy Feb 16 '18 at 16:18
  • That makes sense. – Dallas Caley Feb 16 '18 at 16:21