Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ng add fails to find app.module.ts when using custom tsconfig.json paths #12740

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

Open
seangwright opened this issue Oct 24, 2018 · 11 comments
Open
Labels
area: @schematics/angular freq1: low Only reported by a handful of users who observe it rarely severity3: broken type: bug/fix
Milestone

Comments

@seangwright
Copy link
Contributor

seangwright commented Oct 24, 2018

Bug Report or Feature Request (mark with an x)

- [X ] bug report -> please search issues before submitting
- [X ] feature request

Whether this is a bug or a feature depends on whether or not custom paths in tsconfig.json are supported with the Cli.

Command (mark with an x)

- [X ] add

Versions

Angular CLI: 7.0.2
Node: 10.8.0
OS: win32 x64
Angular: 7.0.0
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Repro steps

  • ng new app-name (pick defaults)
  • Add "paths": { "@app/*": ["src/app/*"] } to tsconfig.json
  • Update main.ts to use this new path
    import { AppModule } from '@app/app.module';
    import { environment } from './environments/environment';
  • ng add @angular/material
  • Select Yes for ? Set up browser animations for Angular Material?

Repository all set up to reproduce this error is available here.
Just clone and type ng add @angular/material.

The log given by the failure

Could not read Angular module file: /src/@app/app.module.ts

Desired functionality

Cli handles custom paths in tsconfig.json.

Mention any other details that might be useful

Here is where material tries to get the app.module.ts path
https://github.com/angular/material2/blob/985774a4eaa14d1dcbf1ad96ab176043d38f433e/src/lib/schematics/ng-add/setup-project.ts#L56

Here is where the path to app.module.ts is being calculated in the schematics code

export function getAppModulePath(host: Tree, mainPath: string): string {

I believe the above link is what is causing the problem.

I've always preferred absolute urls in Angular apps compared to the relative paths (which become very difficult to read for nested components).

Adding custom paths to tsconfig.json works pretty well to solve this problem. VSCode works fine with it and the Cli has no other issues I've run into.

If using paths isn't officially supported does the Angular team recommend using relative paths like import { MyApiService } from '../../../../../my-api.service'?

@alan-agius4
Copy link
Collaborator

Relates to
#12729

@alan-agius4 alan-agius4 added freq1: low Only reported by a handful of users who observe it rarely severity3: broken area: @schematics/angular labels Oct 25, 2018
@ngbot ngbot bot added this to the needsTriage milestone Oct 25, 2018
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Oct 25, 2018
@serridavide
Copy link

Did anyone find a workaround for this issue? I'm trying to add angular material to an existing project and run into this issue. Can someone help me to get it working?

@Splaktar
Copy link
Contributor

Splaktar commented Feb 22, 2021

I just wanted to bump this and say that with Nx and people learning TS more, these custom path mappings are very common. I would suggest moving the frequency of this issue up from low to medium.

This is something that Angular Material users have been running into for 3 years now when using our ng add schematic.

Also based on my investigation in #20118, this is still occuring with 11.2.1.

@alan-agius4
Copy link
Collaborator

I had a look at this and continuing on what @Splaktar mentioned in #20118, in https://github.com/angular/components/blob/8f558eeb7e475da54ad69e85ec07229fb4b0c3e9/src/cdk/schematics/utils/ast/ng-module-imports.ts#L16 the tree.read is invoked with an inexistent path. Schematics are not aware of specific TypeScript path mappings logic as it works similar to the Node.JS file system and hence it is correctly failing.

The module needs to be provided prior to passing it to tree.read. Since, the module resolution logic, is within the Angular Components schematic, it does appear to me that this is more of an Angular Material bug, where path mappings are not supported by the ng-add schematic.

I did a high level example on what needs to be done in the schematic:

const workspace = await getWorkspace(host);
const project = getProjectFromWorkspace(workspace, options.project);
let appModulePath = getAppModulePath(host, getProjectMainFile(project));

if (!host.exits(appModulePath)) {
  const tsConfig = project.targets.get('build')?.options?.tsConfig;
  if (typeof tsConfig === 'string') {
    const { config } = ts.readConfigFile(tsConfig, host.read);
    const { resolvedModule } = ts.resolveModuleName(appModulePath, getProjectMainFile(project), config.options, {
      readFile: function (fileName: string): string {
        return host.read(fileName).toString().replace(/^\uFEFF/, '');
      },
      directoryExists: function (directoryName: string): boolean {
        // When the path is file getDir will throw.
        try {
          const dir = host.getDir(directoryName);

          return !!(dir.subdirs.length || dir.subfiles.length);
        } catch {
          return false;
        }
      },
      fileExists: function (fileName: string): boolean {
        return host.exists(fileName);
      },
      realpath: function (path: string): string {
        return path;
      },
      getCurrentDirectory: function () {
        return host.root.path;
      },
    });

    appModulePath = resolvedModule.resolvedFileName;
  }
}

Alternatively, for a simpler approach an addition option can be added that would allow the users to provide the module path.

ng add @angular/material --module /src/app/app.module.ts
const workspace = await getWorkspace(host);
const project = getProjectFromWorkspace(workspace, options.project);
let appModulePath = options.module ?? getAppModulePath(host, getProjectMainFile(project));

@ThisIsIvan
Copy link

Did anyone find a workaround for this issue? I'm trying to add angular material to an existing project and run into this issue. Can someone help me to get it working?

Found a temporary solution: In your main.ts change the import path of AppModule.

For me it looks like this:
import { AppModule } from '@app/app.module'; -> import { AppModule } from './app/app.module';

Absolute path didn't work:

import { AppModule } from 'src/app/app.module';
Could not read Angular module file: /src/src/app/app.module.ts

@Sergiobop
Copy link

This still happens on Angular 17

Setup to fail:

  • In your tsconfig.json add a custom path:
...
    "paths": {
      "@app/*": ["app/*"],
...
  • Then use it in your main.ts:
import { bootstrapApplication } from '@angular/platform-browser';

import { AppComponent } from '@app/app.component';
import { appConfig } from '@app/app.config';

bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));
  • For example, try to add ssr package:
    ng add @angular/ssr

The command fails:

Cannot statically analyze bootstrapApplication call in src/main.ts

  • If you change main.ts to:
import { bootstrapApplication } from '@angular/platform-browser';

import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';

bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));

It works @alan-agius4

@AngelCorre
Copy link

AngelCorre commented Dec 29, 2023

By default Angular 17 create a project that use standalone.
You can change that putting false when you create your project.
ng new nameproject --standalone=false

@JonasDev17
Copy link

JonasDev17 commented Jan 22, 2024

I can confirm this. I'm having the same issue right now:

Cannot statically analyze bootstrapApplication

this happens when I run:

ng add @angular/ssr

EDIT:

I had to change:

import { appConfig } from "app/app.config";

to:

import { appConfig } from "./app/app.config";

adding a ./ to the path

@STotev
Copy link

STotev commented Feb 9, 2024

6 years later and still hasn't been fixed. I can confirm the same behaviour.

Updated the path in main.ts only for the AppModule and finished successfully.

@mbirali
Copy link

mbirali commented Jan 16, 2025

If you still have the same issue with Angular 19, as @JonasDev17 said

Your main.ts file should look like:

import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
bootstrapApplication(AppComponent, appConfig).catch((err) =>
console.error(err)
);

And NOT:

import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from 'app/app.component';
import { appConfig } from 'app/app.config';
bootstrapApplication(AppComponent, appConfig).catch((err) =>
console.error(err)
);

The difference is ./

@kanehjeong
Copy link

Getting this error trying to add @angular/pwa even after copying the other people's examples above line for line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: @schematics/angular freq1: low Only reported by a handful of users who observe it rarely severity3: broken type: bug/fix
Projects
None yet
Development

No branches or pull requests