如何使用 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 app
和 ng 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) 创建单一仓库项目结构的主要内容,如果未能解决你的问题,请参考以下文章
缺少 .angular-cli.json 文件:Angular