Skip to content

(AOT) Cannot find modules when tsconfig paths are used #6973

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nekkon opened this issue Jul 14, 2017 · 10 comments
Closed

(AOT) Cannot find modules when tsconfig paths are used #6973

nekkon opened this issue Jul 14, 2017 · 10 comments

Comments

@nekkon
Copy link

nekkon commented Jul 14, 2017

In my tsconfig.json I have added the following code so that I can import modules using "@orco/.." I am using multiple apps in the same repo. I want to share between apps common modules. The tsconfig below does work properly with ng serve and ng build. It does not work with ng build -prod. Probably it is an AOT problem. I would like to know if there is something else that needs to be done, as I could not find a documented way of doing this. An example of the errors I get: ERROR in C:/Users/nekkon/Desktop/angular/orco-frontend/src/admin/$$_gendir/shared/other/core.root.module.ngfactory.ts (10,21): Cannot find module './core.root.module'.

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

I have a nested tsconfig.app.json which I also added the following code:

{
    "extends": "../../tsconfig.json",
    "compilerOptions": {
      "paths": {
          "@orco/*": ["../shared/*"]
      },
      "outDir": "../out-tsc/app",
      "module": "es2015",
      "baseUrl": "./",
      "types": []
    },
    "exclude": [
      "test.ts",
      "**/*.spec.ts"
    ]
}

My angular-cli.json is below:

{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "project": {
        "name": "orco-frontend"
    },
    "apps": [
        {
            "name": "dm",
            "root": "src/dm",
            "outDir": "dist/dm",
            "assets": [
                { "glob": "**/*", "input": "./assets/", "output": "./assets/" },
                { "glob": "favicon.ico", "input": "./", "output": "./" },
                { "glob": "**/*", "input": "../shared/assets", "output": "./assets/" }
            ],
            "index": "index.html",
            "main": "main.ts",
            "polyfills": "../shared/other/polyfills.ts",
            "test": "test.ts",
            "tsconfig": "tsconfig.app.json",
            "testTsconfig": "tsconfig.spec.json",
            "prefix": "dm",
            "styles": [
                "styles.scss",
                "../shared/other/styles.scss"
            ],
            "scripts": [],
            "environmentSource": "environments/environment.ts",
            "environments": {
              "dev": "environments/environment.ts",
              "prod": "environments/environment.prod.ts"
            }
        },
        {
            "name": "protocol",
            "root": "src/protocol",
            "outDir": "dist/protocol",
            "assets": [
                { "glob": "**/*", "input": "./assets/", "output": "./assets/" },
                { "glob": "favicon.ico", "input": "./", "output": "./" },
                { "glob": "**/*", "input": "../shared/assets", "output": "./assets/" }
            ],
            "index": "index.html",
            "main": "main.ts",
            "polyfills": "../shared/other/polyfills.ts",
            "test": "test.ts",
            "tsconfig": "tsconfig.app.json",
            "testTsconfig": "tsconfig.spec.json",
            "prefix": "protocol",
            "styles": [
                "styles.scss",
                "../shared/other/styles.scss"
            ],
            "scripts": [],
            "environmentSource": "environments/environment.ts",
            "environments": {
              "dev": "environments/environment.ts",
              "prod": "environments/environment.prod.ts"
            }
        },
        {
            "name": "admin",
            "root": "src/admin",
            "outDir": "dist/admin",
            "assets": [
                { "glob": "**/*", "input": "./assets/", "output": "./assets/" },
                { "glob": "favicon.ico", "input": "./", "output": "./" },
                { "glob": "**/*", "input": "../shared/assets", "output": "./assets/" }
            ],
            "index": "index.html",
            "main": "main.ts",
            "polyfills": "../shared/other/polyfills.ts",
            "test": "test.ts",
            "tsconfig": "tsconfig.app.json",
            "testTsconfig": "tsconfig.spec.json",
            "prefix": "admin",
            "styles": [
                "styles.scss",
                "../shared/other/styles.scss"
            ],
            "scripts": [],
            "environmentSource": "environments/environment.ts",
            "environments": {
              "dev": "environments/environment.ts",
              "prod": "environments/environment.prod.ts"
            }
        }
    ],
    "e2e": {
        "protractor": {
            "config": "./protractor.conf.js"
        }
    },
    "lint": [
      {
          "project": "src/admin/tsconfig.app.json"
      },
      {
          "project": "src/dm/tsconfig.app.json"
      },
      {
          "project": "src/protocol/tsconfig.app.json"
      },
      {
          "project": "src/tsconfig.spec.json"
      },
      {
          "project": "e2e/tsconfig.e2e.json"
      }
    ],
    "test": {
        "karma": {
            "config": "./karma.conf.js"
        }
    },
    "defaults": {
        "styleExt": "css",
        "component": {}
    }
}
 
P.S. Vscode detects the module and does not show an error. The module is not inside the project's folder.
@nekkon nekkon changed the title Cannot find modules using tsconfig paths Cannot find modules when tsconfig paths are used Jul 14, 2017
@nekkon nekkon changed the title Cannot find modules when tsconfig paths are used (AOT) Cannot find modules when tsconfig paths are used Jul 14, 2017
@nekkon
Copy link
Author

nekkon commented Jul 16, 2017

Don't know if the reason behind my problem is the same with: #6632. I don't understand how come ng serve and ng build work fine but ng build --prod doesn't. I think the problem is with AOT.

@coldhamix
Copy link

coldhamix commented Jul 21, 2017

I am experiencing the same issue. It doesn't even work if you switch from tsconfig path to plain imports like import { DemoComponent } from '../../shared/components/demo'

A bit more detailed about my case: https://stackoverflow.com/questions/45234210/aot-compiler-generates-wrong-import

@EricABC
Copy link

EricABC commented Jul 25, 2017

This problem seems to occur in shared library scenarios. The workaround for me is to use a tsconfig that is in a common root path of all shared libraries. You can still set the root of the app and reference the tsconfig as "../../tsconfig.hacketyhack.json". In the error you'll see $$_gendir is already in the admin app. The virtual file system represented by $$_gendir seems to start from the tsconfig location and can't navigate above itself. An additional AOT problem that resembles the rc.0 -> rc.1 fix occurs (even in rc.1) if the entrypoint ts is not included in the tsconfig (even though ng will include the main automatically). So you need to make a tsconfig for each app in the common root or include paths to all main.ts's for libraries sharing this tsconfig.

@nekkon
Copy link
Author

nekkon commented Jul 26, 2017

An official answer would be much appreciated. I believe that this should be fixed than implementing a workaround. The same code and file structure should be working with AOT from the moment ng serve/build works without it, don't you agree?

@filipesilva
Copy link
Contributor

Marking as a duplicate of #7087 since it's being tracked there already.

@filipesilva filipesilva marked this as a duplicate of #7087 Jul 28, 2017
@nekkon
Copy link
Author

nekkon commented Jul 31, 2017

@EricABC Could you explain the workaround? I am trying with no success. I need this and from what I see it is not considered urgent by the angular-cli team, so I will have to try your workaround.
I get the following error after altering tsconfig.protocol.json

ERROR in ./src/protocol/main.ts Module not found: Error: Can't resolve './../$$_gendir/protocol/app/app.module.ngfactory' in 'C:\Users\nekkon\Desktop\angular\orco-frontend\src\protocol' @ ./src/protocol/main.ts 3:0-86 @ multi ./src/protocol/main.ts

tsconfig.protocol.json:

    "extends": "../tsconfig.json",
    "compilerOptions": {
      "paths": {
          "@orco/*": ["../shared/*"]
      },
      "outDir": "../out-tsc/app",
      "module": "es2015",
      "baseUrl": "./protocol",
      "types": []
    },
    "exclude": [
      "test.ts",
      "**/*.spec.ts",
      "admin/**",
      "dm/**"
    ]
}

ng serve and ng build works fine again. ng build --prod (with aot) does not

@EricABC
Copy link

EricABC commented Jul 31, 2017

@nekkon Perhaps the tsconfig needs to go up one more directory. I think paths using a '..' causes typescript to calculate a common root internally (not 100% sure), which is why you would still get an error for 'app' even though its not 'shared'.
My mono-repository looks something like:

  • tsconfig.json (for IDE)
  • package.json
  • tslint.json
  • .angular-cli.json
  • Typescript/tsconfig.base.json
  • Typescript/tsconfig.(build/app/sample/spec).json
  • Typescript/karma.conf.js
  • Typescript/modules/modules-go-here
  • Typescript/samples/mini-apps-used-by-devs-to-design-components
  • Typescript/config/everything-else-that-doesnt-break-if-navigating-up-paths

I elevate several items to the root of the mono-repo, including tslint, angular-cli config, etc...
Only one node-modules folder at the root to avoid difficult-to-diagnose issues with inconsistent implementations of node resolution between several tools and karma/webpack spec resolution problems.
karma config similarly needs to not use any ..'s, so my tests.ts uses
const context = require.context('./modules', true, /\.spec\.ts$/);

All tsconfigs extend tsconfig.base.json
all have paths "@abcoa/": "./modules/" or "./Typescript/modules/*" for the root tsconfig
The .angular-cli.json has a first app called 'tests' that uses a root of 'Typescript' and './tsconfig.spec.json'. It points to a junk main.ts in Typescript/config because you can't have a tests-only app.
I think the need for a single test app as the first app is fixed after rc.1.

I use 1.3.0-rc.1+

@nekkon
Copy link
Author

nekkon commented Aug 2, 2017

Thanks @EricABC ! I managed to make it work and it builds properly with AOT.

@josh-sachs
Copy link

josh-sachs commented Oct 5, 2017

Spent a great deal of time trying to understand this issue as well. It seems that ngc doesn't respect baseUrl or rootDir tsc arguments when generating the import statements within ngfactory modules.

As @EricABC mentioned, it appears the tsconfig file you target with ngc must exist at the most common root shared by all of your project's libraries.

Solution:

-- src/
---- tsconfig-base.json
---- tsconfig-ngc.platform-browser.json
---- app/
---- packages/
---- platform-browser/
------ aot/
-------- generated/
-------- main.ts
-------- tsconfig.json
------ main.ts
------ index.d.ts
---- platform-webworker/
------ aot/
-------- generated/
-------- main.ts
-------- tsconfig.json
------ main.ts
------ index.d.ts

When running ngc, previously I would target a platform config file, which messed up ngfactory import paths (ultimately the bug, because I provided a rootDir and baseUrl of "../../")
ngc -p src/platform-browser/aot/tsconfig.json

The solution is the tsconfig-ngc.platform-browser.json file in the source root:

{
    "extends": "./platform-browser/aot/tsconfig.json",
    "files": [        
        "platform-browser/main.ts",
        "platform-browser/index.d.ts"
    ],    
    "angularCompilerOptions": {
        "genDir": "platform-browser/aot/generated",
        "skipMetadataEmit": true
    }
}

I target that file with ngc and the original ./platform-browser/aot/tsconfig.json file with my build processes.

ngc -p src/tsconfig-ngc.platform-browser.json

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants