如何使用 angular-cli (6.x) 创建单一仓库项目结构

Posted

技术标签:

【中文标题】如何使用 angular-cli (6.x) 创建单一仓库项目结构【英文标题】:How to create a mono-repo project structure with angular-cli (6.x) 【发布时间】:2018-12-07 23:47:07 【问题描述】:

我想使用 angular-cli 生成一个新的工作区

目前唯一的方法是运行:

ng new asdf
cd asdf
ng g application whatever

但是所有src/ 文件仍然存在(以及现在不一致存储的项目的原始 angular.json 信息)。如果没有src 文件夹,就无法创建新的存储库...当我使用自定义原理图执行此操作时,基本上复制了 angular-cli 的 ng-new 并删除了 https://github.com/angular/angular-cli/blob/6449a753641340d8fc19a752e1a1ced75f974efa/packages/schematics/angular/ng-new/index.ts#L61 schematic('application', applicationOptions),

每当我运行它...

$ 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)

只有 e2e 文件被放入projects/angular.json 文件大部分保持为空:


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

我怀疑这与应用程序示意图中出现静默失败或路径关闭有关...但我想先检查是否有更简单/更首选的方法。

$ 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     

编辑注意我熟悉 3rd-party 库(例如 Nrwl/Nx),但我试图避免这些。我也把这个问题发到了 GitHub:https://github.com/angular/angular-cli/issues/11402

【问题讨论】:

我看到你说,“但是所有的 src/ 文件仍然存在(以及现在不一致存储的项目的原始 angular.json 信息)。没有没有办法创建新的 repo src 文件夹。”您有一个***工作区,其中包含一堆子应用程序。可以提交***工作区,并且每个应用程序都作为子模块提交(例如在 git 中)。每个都有自己的开发流程等。顶层可以用作子模块的组合机制(同样,每个模块都有不同的流程),所有这些都在一个父仓库中。那不行吗? 我正在尝试使用 angular-cli 来完成这一切。如果我使用 ng new asdf 然后添加一些(比如 5 个)“应用程序”(使用 ng g app)...你将在 asdf/src/ 内有一个应用程序,在 asdf/projects/ 内有 5 个应用程序都共享一个包.json / angular.json 文件。甚至 e2e 测试也在不同的位置(asdf/e2e/ 中的一个和asdf/projects/ 中的 5 个)。这就是我要解决的不一致问题。我宁愿ng new 有一个--blank 选项(或其他东西),然后就可以在项目中拥有所有东西/而不必手动移动东西。 嗯...我不确定我是否认为作为单一回购协议的不一致,每个模块都有自己的 e2e 测试等似乎与这个想法一致,等等。我有点挣扎的一件事是 package.json 的事情。假设我想在其中一个子应用程序中使用 ngrx。我必须在*** package.json 中进行安装等。由于我无法为每个应用程序指定不同的 package.jsons,所以 ng g 应用程序最终看起来像是一个美化的功能模块。当然,我可以创建不同的“舞台”子应用程序作为特定的合成器,但是那里的流程开始变得模糊。 从组织/文件夹结构的角度来看是不一致的。就我个人而言,我不使用 git 子模块(看不到重点),因此不需要单独的 package.json 文件(尤其是摇树等)。它也不会真正影响流程,因为合并冲突等是由修改重叠文件引起的。仍然可以对 repo 中的特定应用程序进行拉取请求,并且一个“领导”可以为一个团队审查所有这些请求。 我也相信这是不一致的行为,我的意思是我们公司开发的大多数项目都有客户端和管理端。目前,客户端位于 projectname -> src 下,而管理端位于 project-name->projects->app-name->src 下,我认为这不是一个好的结构。顺便说一句,我们仍然可以在“项目”中创建客户端目录并将初始 src 文件夹移动到那里,但是我们必须基于此更改所有它的初始路径,所以如果我们必须手动执行此操作。 【参考方案1】:

目前没有办法按照我的意愿进行操作。

hacky 的解决方法是运行:

ng new <mono-repo name>

cd 进去 (cd <mono-repo name>)

生成第一个应用名称 (ng generate application <app-name>)

然后删除原来的src/e2e文件夹(rm -rf src e2e)和angular.json中对应的条目。

从那时起,无论何时生成库/应用程序,所有内容都将位于项目文件夹中。

【讨论】:

因为 Angular 7 --createApplication=false 应该可以解决问题【参考方案2】:

如果您不希望您的初始应用程序驻留在 /src 中,您可以按照以下两个步骤操作:

ng new my-workspace --create-application=false --defaults
--create-application 告诉 Angular CLI 不要生成初始应用程序。 --defaults 告诉 Angular CLI 不要提示您有关路由和 CSS 预处理器的信息
ng generate application my-app

通过这两个步骤,您最终将得到如下文件结构:

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

您会在projects文件夹中找到您的应用程序及其对应的e2e应用程序:

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

【讨论】:

【参考方案3】:

改用ng g application project-name

结果

还有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"

【讨论】:

ng g appng g application 是同一件事,您必须在已经建立的项目中进行(如上所述,该项目具有 src 文件夹)。这不能回答我的问题 显然我已经习惯使用将app 别名为application 的示意图。我已经编辑了我的问题以澄清,但这是我的错字/没有影响我的意图 我原本也有同样的想法,但重读并看到他已经知道这一点,正在寻找其他东西。我认为 g app 基本上创建了一个美化的功能模块;是的,它可以独立运行和测试......有点。它仍然依赖于工作区 package.json。如果您以 npm mod 或类似的形式发布(它会在 deps 中拉出),这很好,但并不是真正的单一回购必杀技。您的项目“应用程序”仍然需要由包含 package.json 的工作区组成。在最近的一份合同中,我自己一直在做这件事。有趣的问题要解决。【参考方案4】:

我在这里是如何使用 Nx 和 Angular CLI 执行此操作的指南 here 最简单的方法是从生成一个空的 Angular CLI 项目开始:

ng new --createApplication false

或者如果您使用 NX:

create-nx-workspace myworkspacedemo

从这里您可以在 app 文件夹中生成应用程序:

ng g app myapp

并在 libs 文件夹中生成库:

ng g lib mylib

如果您使用的是 NX 原理图,这还会提示您进行许多额外的配置选项,例如生成延迟加载的模块、路由、使用 Jest 等...

【讨论】:

【参考方案5】:

好吧,创建 monorepo 架构太容易了 让我们看看

通过这样做,您指定了一个不包含任何架构的架构 应用。这给了你这样的代码......

哦,看来您已经创建了架构 现在进入您的代码编辑器并创建您的应用程序

现在是时候检查一切是否正常。 让我们使用您想要的任何随机端口运行...

您可以在单一架构中拥有多个应用程序,它们都将使用相同的节点模块 因此,将来一旦您更新了任何模块,您的所有应用程序都将访问更新后的应用程序,因此无需逐个更新它们

除此之外,您还可以在不同的端口上运行所有应用程序并单独创建构建

【讨论】:

以上是关于如何使用 angular-cli (6.x) 创建单一仓库项目结构的主要内容,如果未能解决你的问题,请参考以下文章

ng:使用 angular-cli 创建新项目时找不到命令

缺少 .angular-cli.json 文件:Angular

text 使用angular-cli创建新的角度应用程序

如何使用 angular-cli 只执行一个测试规范

如何在 angular-cli 中使用 bootstrap mixins

如何在基于 angular-cli 的混合应用程序中使用 ng-annotate