3

I'd like to use the angular-cli to generate a new workspace

The only way to do this at the moment is to run:

ng new asdf
cd asdf
ng g application whatever

but then all of the src/ files remain (and the original angular.json info for a project that is now inconsistently stored). There's no way to create a new repo without the src folder... and when I do this using a custom schematic by essentially duplicating angular-cli's ng-new and removing https://github.com/angular/angular-cli/blob/6449a753641340d8fc19a752e1a1ced75f974efa/packages/schematics/angular/ng-new/index.ts#L61 schematic('application', applicationOptions),

Whenever I run it...

$ ng new asdf -c=my-schematic
$ cd asdf
$ ng g application whatever
    {"inlineStyle":false,"inlineTemplate":false,"routing":false,"prefix":"app","style":"css","skipTests":false,"skipPackageJson":false,"name":"whatever"}
CREATE projects/whatever-e2e/protractor.conf.js (752 bytes)
CREATE projects/whatever-e2e/src/app.e2e-spec.ts (304 bytes)
CREATE projects/whatever-e2e/src/app.po.ts (208 bytes)
CREATE projects/whatever-e2e/tsconfig.e2e.json (219 bytes)

Only the e2e files get put into projects/ and the angular.json file remains mostly empty:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {},
  "cli": {
    "defaultCollection": "my-schematic"
  }
}

I suspect this has to do with something silently failing in the application schematic or a path being off... but I wanted to check first if there was an easier / more preferred way.

$ ng --version                                                 

Angular CLI: 6.1.0-rc.0                                        
Node: 10.1.0                                                   
OS: win32 x64                                                  
Angular: 6.0.7                                                 
... animations, common, compiler, compiler-cli, core, forms    
... http, language-service, platform-browser                   
... platform-browser-dynamic, router                           

Package                      Version                           
------------------------------------------------------         
@angular-devkit/architect    0.7.0-rc.0                        
@angular-devkit/core         0.6.8                             
@angular-devkit/schematics   0.6.8                             
@angular/cdk                 6.3.1                             
@angular/cli                 6.1.0-rc.0                        
@angular/material            6.3.1                             
@schematics/angular          0.6.8                             
@schematics/update           0.7.0-rc.0                        
rxjs                         6.2.1                             
typescript                   2.7.2     

Editing to note I'm familiar about 3rd-party libraries (e.g. Nrwl/Nx) but I'm trying to avoid those. I also posted this issue to GitHub: https://github.com/angular/angular-cli/issues/11402

martzcodes
  • 404
  • 5
  • 16
  • I see you say, "but then all of the src/ files remain (and the original angular.json info for a project that is now inconsistently stored). There's no way to create a new repo without the src folder." You have a top level workspace, with a bunch of sub applications. The top level workspace can be committed, and each app committed as a sub module (in git for instance). Each has it's own dev flow, etc. The top level can be used as the composition mechanism for your sub modules (again, each and all having different flows), all in one parent repo. That won't do? – Tim Consolazio Jun 28 '18 at 21:02
  • 1
    I'm trying to do this all with the angular-cli. If I use `ng new asdf` and then add a few (say 5) "applications" to it (using `ng g app`)... you'd have one app inside `asdf/src/` and 5 apps inside `asdf/projects/` all sharing one package.json / angular.json files. Even the e2e tests are in different spots (one in `asdf/e2e/` and 5 in `asdf/projects/`). That's the inconsistency I'm trying to fix. I'd rather `ng new` have a `--blank` option (or something) and then just be able to have everything in projects/ without having to manually move stuff. – martzcodes Jun 29 '18 at 00:58
  • Hmm...I'm not sure I see that as an inconsistency insofar as a mono repo, each module having it's own e2e tests etc. would seem to be consistent with the idea, etc. The one thing that I struggle a bit with is the package.json thing. Say I want to use ngrx in one of the sub apps. I have to do the install etc. in the top-level package.json. Since I can not specify different package.jsons for each app, what ng g application ultimately seems like, is a glorified feature module. Sure I can create different "stage" sub-apps as specific compositors, but the flow starts to get vague there. – Tim Consolazio Jun 29 '18 at 12:33
  • It's inconsistent from an organization / folder structure perspective. Personally I don't use git submodules (don't see the point) so there isn't a need for separate package.json files (especially with tree-shaking, etc). It also doesn't really affect flow because merge conflicts and such arise from modifying overlapping files. Can still have Pull Requests for the specific applications inside the repo, and one "lead" can review them all for a team. – martzcodes Jun 29 '18 at 13:44
  • I too believe that it's inconsistent behavior, I mean most of the projects we develop in our company has client and admin side. Currently Client side comes under projectname -> src and admin side goes under project-name->projects->app-name->src which is not a good structure in my opinion. BTW We still can create client directory inside "projects" and move initial src folder there but then we have to change all of it's initial paths based on that, so if we have to do that manually. – BhargavG Jul 03 '18 at 05:21
  • @BhargavG yeah, that's what led to this post and my feature request on github – martzcodes Jul 03 '18 at 14:14
  • Hey what ever happend to this? Do you have an example project of this working? – Kay Aug 15 '18 at 11:39
  • Please have a look at my repo at https://github.com/ShubhenduVaid/angularCLI-monorepo. 1. I have used monorepo structure and angular cli v6. 2. Steps are in Readme. 3. As a bonus i have used Service as an Interface too. Let me know if any questions. – Shubhendu Vaid Aug 28 '18 at 08:01
  • I don't think you understood my question. I wanted to create a new workspace with all original src and e2e files in the projects folder by default. Meaning as I add applications and libraries to the project I don't want one app to be orphaned while the others are in projects. There currently isn't a way to do this. The hacky workaround is to run `ng new `, cd into it, generate the first app name (`ng new application `) and then remove the original src / e2e folders (`rm -rf src e2e`) and the corresponding entry in `angular.json` – martzcodes Aug 28 '18 at 14:36
  • Removing the original src / e2e folders (rm -rf src e2e) and the corresponding entry in angular.json is a one time job. After this all libraries,applications will be in projects folder. To have the libraries in a separate folder other than projects is not possible yet. But is accepted as a feature in future versions https://github.com/angular/angular-cli/issues/11927 – Shubhendu Vaid Aug 29 '18 at 10:33

5 Answers5

4

There currently isn't a way to do this the way I intend.

The hacky workaround is to run:

ng new <mono-repo name>

cd into it (cd <mono-repo name>)

generate the first app name (ng generate application <app-name>)

and then remove the original src / e2e folders (rm -rf src e2e) and the corresponding entry in angular.json.

From then on whenever libraries / applications are generated everything will be in the projects folder.

Zach Newburgh
  • 563
  • 3
  • 11
martzcodes
  • 404
  • 5
  • 16
4

If you don't want your initial application to resides in /src, you can follow these 2 steps:

ng new my-workspace --create-application=false --defaults
  • --create-application tells the Angular CLI not to generate an initial application.
  • --defaults tells the Angular CLI not to prompt you about routing and CSS preprocessor
ng generate application my-app

With these two steps, you will end up with a file structure like this:

.
├── .git/
├── node_modules/
├── projects/
├── .editorconfig
├── .gitignore
├── README.md
├── angular.json
├── package.json
├── tsconfig.json
├── tslint.json
└── yarn.lock

And you will find your application and its corresponding e2e application in the projects folder:

projects/
├── my-app/
└── my-app-e2e/
1

I here is a guide how to do this using Nx and Angular CLI here The easiest is just to start with generating an empty Angular CLI project:

ng new --createApplication false

or if you use NX:

create-nx-workspace myworkspacedemo

From here you can generate apps in the app folder with:

ng g app myapp

And generate libs in the libs folder with:

ng g lib mylib

If you are using NX schematics this will also prompt you for a lot of extra configuration options such as generating lazy loaded modules, routing, use Jest etc...

lyzz
  • 128
  • 1
  • 9
0

Try ng g application {project-name} instead.

Result

enter image description here

And Angular.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "mono-repo": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/mono-repo",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/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": "mono-repo:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "mono-repo:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "mono-repo:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.spec.json",
            "karmaConfig": "src/karma.conf.js",
            "styles": [
              "styles.css"
            ],
            "scripts": [],
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ]
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "src/tsconfig.app.json",
              "src/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    },
    "mono-repo-e2e": {
      "root": "e2e/",
      "projectType": "application",
      "architect": {
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "mono-repo:serve"
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": "e2e/tsconfig.e2e.json",
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    },
    "project-alpha": {
      "root": "projects/project-alpha/",
      "sourceRoot": "projects/project-alpha/src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/project-alpha",
            "index": "projects/project-alpha/src/index.html",
            "main": "projects/project-alpha/src/main.ts",
            "polyfills": "projects/project-alpha/src/polyfills.ts",
            "tsConfig": "projects/project-alpha/tsconfig.app.json",
            "assets": [
              "projects/project-alpha/src/favicon.ico",
              "projects/project-alpha/src/assets"
            ],
            "styles": [
              "projects/project-alpha/src/styles.css"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "projects/project-alpha/src/environments/environment.ts",
                  "with": "projects/project-alpha/src/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": "project-alpha:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "project-alpha:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "project-alpha:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "projects/project-alpha/src/test.ts",
            "polyfills": "projects/project-alpha/src/polyfills.ts",
            "tsConfig": "projects/project-alpha/tsconfig.spec.json",
            "karmaConfig": "projects/project-alpha/karma.conf.js",
            "styles": [
              "projects/project-alpha/src/styles.css"
            ],
            "scripts": [],
            "assets": [
              "projects/project-alpha/src/favicon.ico",
              "projects/project-alpha/src/assets"
            ]
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "projects/project-alpha/tsconfig.app.json",
              "projects/project-alpha/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    },
    "project-alpha-e2e": {
      "root": "projects/project-alpha-e2e/",
      "projectType": "application",
      "architect": {
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "projects/project-alpha-e2e/protractor.conf.js",
            "devServerTarget": "project-alpha:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "project-alpha:serve:production"
            }
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": "projects/project-alpha-e2e/tsconfig.e2e.json",
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "mono-repo"
}
TYMG
  • 297
  • 1
  • 6
  • 14
  • `ng g app` and `ng g application` are the same thing and you have to do it inside an already established project (that has the src folder, as described above). This does not answer my question – martzcodes Jun 29 '18 at 00:52
  • apparently I've been used to using a schematic that aliases `app` to `application`. I've edited my question to clarify but it was a typo on my part / didn't impact my intent – martzcodes Jun 29 '18 at 01:19
  • 1
    I originally had the same thought, but reread and saw he already knew this and is looking for something else. I've come to the opinion that g app basically creates a glorified feature module; yes it can be run and tested independently...sort of. It's still dependent on the workspace package.json. This is fine if you publish as an npm mod or some such (it'll yank in the deps), but isn't really that mono-repo nirvana. Your project "apps" still need to be composed by a workspace that contains a package.json. I've been working on this myself at a recent contract. Interesting problem to solve. – Tim Consolazio Jun 29 '18 at 15:02
0

Okay it's too easy to create a monorepo architecture
let's see

enter image description here

By doing this you specified an architecture without consisting any application. this gives you code like this...

enter image description here

OOoh it seems you have created your architecture
now come into your code editor and now create your application enter image description here

enter image description here

Now time to check if everything works well or not.
let's run with any random port where you want...

enter image description here

you can have multiple application in single architecture and they all would going to use the same node modules
so in future once you update your any module, all your applications would be accessing the updated one so no need to update them one by one

apart from you can run all your applications on different different ports and create the build as separately

enter image description here

Rudra
  • 109
  • 2
  • 7