Angular-cli: The "ng generate" command does not work with custom "sourceRoot" property in "angular.json"

Created on 7 May 2018  路  11Comments  路  Source: angular/angular-cli

Versions

Angular CLI: 6.0.0
Node: 10.0.0
OS: linux x64
Angular: 6.0.0
... animations, cli, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.6.0
@angular-devkit/build-angular     0.6.0
@angular-devkit/build-optimizer   0.6.0
@angular-devkit/core              0.6.0
@angular-devkit/schematics        0.6.0
@ngtools/webpack                  6.0.0
@schematics/angular               0.6.0
@schematics/update                0.6.0
rxjs                              6.1.0
typescript                        2.7.2
webpack                           4.6.0

Repro steps

  1. Create a new app: ng new xyz
  2. Rename the src directory to foo
  3. In angular.json change all occurrences of src to foo:
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "xyz": {
      "root": "",
      "sourceRoot": "foo",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/xyz",
            "index": "foo/index.html",
            "main": "foo/main.ts",
            "polyfills": "foo/polyfills.ts",
            "tsConfig": "foo/tsconfig.app.json",
            "assets": [
              "foo/favicon.ico",
              "foo/assets"
            ],
            "styles": [
              "foo/styles.css"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "foo/environments/environment.ts",
                  "with": "foo/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "xyz:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "xyz:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "xyz:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "foo/test.ts",
            "polyfills": "foo/polyfills.ts",
            "tsConfig": "foo/tsconfig.spec.json",
            "karmaConfig": "foo/karma.conf.js",
            "styles": [
              "styles.css"
            ],
            "scripts": [],
            "assets": [
              "foo/favicon.ico",
              "foo/assets"
            ]
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "foo/tsconfig.app.json",
              "foo/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    },
    "xyz-e2e": {
      "root": "e2e/",
      "projectType": "application",
      "architect": {
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "xyz:serve"
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": "e2e/tsconfig.e2e.json",
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "xyz"
}
  1. Generate new component: ng g c bar
  2. When it fails, run: ng g c bar --skip-import

Observed behavior

  1. Command ng g c bar fails with an error: Could not find an NgModule. Use the skip-import option to skip importing in NgModule.
  2. Command ng g c bar --skip-import creates the component in a wrong directory:
CREATE src/app/bar/bar.component.css (0 bytes)
CREATE src/app/bar/bar.component.html (22 bytes)
CREATE src/app/bar/bar.component.spec.ts (607 bytes)
CREATE src/app/bar/bar.component.ts (257 bytes)

Desired behavior

ng g c bar generates component bar in foo/app/bar

CREATE foo/app/bar/bar.component.css (0 bytes)
CREATE foo/app/bar/bar.component.html (22 bytes)
CREATE foo/app/bar/bar.component.spec.ts (607 bytes)
CREATE foo/app/bar/bar.component.ts (257 bytes)

Most helpful comment

@matheusdavidson yes. Global angular cli install:

Angular CLI: 6.0.1
Node: 8.11.1
OS: win32 x64

$ ng new ng-demo --skip-install --skip-imports

Then edit angular.json, change sourceRoot to client and all other reference to src to client. New components installed in src(wrong!), without --skip-imports you get and error:

$ ng g c core --skip-import --dry-run
CREATE src/app/core/core.component.html (23 bytes)
CREATE src/app/core/core.component.spec.ts (614 bytes)
CREATE src/app/core/core.component.ts (261 bytes)
CREATE src/app/core/core.component.css (0 bytes)

All 11 comments

same as: #10653, #10672, i have the same problem

Closing...
Duplicate of #10653

@Brocco Please reopen this issue, it is different than #10653 .

The issue described here is that ng generate is not working when the value of sourceRoot property in angular.json is set to something different than the default src. For example "sourceRoot": "foo".

It seems that the generate command is completely ignoring this property and always expects the application files to be in src directory. Hence the "Could not find an NgModule..." error and component files created in src/app with the --skip-import option (whilst they should be in foo/app).

For comparison, it is working fine in Angular CLI 1.7.4 with Angular 5.2.10. In .angular-cli.json the root property is set to foo and everything is working as expected:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "apps": [
    {
      "root": "foo",
      "outDir": "foo/.dist",
      ...

Just to point out the difference, issue #10653 is that for some reasons ng g component home --skip-import generates a component in a wrong location, when it was expected to be in src/app.

@mwilkosinski, its the same problem, its getting your new source root, but it doesn鈥檛 find any module because its looking in the wrong place, as stated in #10653.

If you want to confirm what i鈥檓 saying, generate a module before, it will put in the wrong place, then generate a component under that module, it will work, but everything will be in the wrong place.

@matheusdavidson maybe the underlying cause is the same in both cases, I don't know, but on the surface these issues are different.

Issue #10702:

The ng generate command creates modules, components, etc., inside the src directory, while according to sourceRoot it should place them in a directory foo. Directory src shouldn't exist at all.

So directory src has been wrongly created, but its location is what it would normally be: under my project's root directory.

Issue #10653:

The ng generate command creates modules, components, etc., inside src directory, which is created in a completely wrong place. The sourceRoot property in angular.json in this case has a default value src.

@mwilkosinski, update to 6.0.1, this update solved my problem, pretty sure it will fix yours.

Same problem here, same example of the author, not working, running on 6.0.1

@gremo, did you update you local ng cli as well?

rm -rf node_modules
npm uninstall --save-dev angular-cli
npm install --save-dev @angular/cli@latest
npm install

@matheusdavidson yes. Global angular cli install:

Angular CLI: 6.0.1
Node: 8.11.1
OS: win32 x64

$ ng new ng-demo --skip-install --skip-imports

Then edit angular.json, change sourceRoot to client and all other reference to src to client. New components installed in src(wrong!), without --skip-imports you get and error:

$ ng g c core --skip-import --dry-run
CREATE src/app/core/core.component.html (23 bytes)
CREATE src/app/core/core.component.spec.ts (614 bytes)
CREATE src/app/core/core.component.ts (261 bytes)
CREATE src/app/core/core.component.css (0 bytes)

I just ran into this issue myself. I am using the CLI with a .NET Core app and I have the code split into different folders. One for Server (.Net Core API) and one for Client (Angular App).

There is a workaround to get the CLI to generate the component/module/service/etc. in the correct location by using the (undocumented) --path option.

$ ng generate service app.config --path=Client

I found the --path option by looking at this line in the Service schematic. If you don't specify a path, it defaults to creating one that has the src directory hardcoded into it.

if (options.path === undefined) {
  const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
  options.path = `/${project.root}/src/${projectDirName}`;
}

I still think this is an issue as it isn't actually using the configuration that is set in angular.json file. Currently this is unexpected behaviour.

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._

Was this page helpful?
0 / 5 - 0 ratings