有没有更好的方法来使用库构建 Angular monorepo 应用程序?
Is there a better way to build an Angular monorepo app with libraries?
我的 Angular monorepo 项目中有几个应用程序。我还编写了大约 5 个库以在应用程序中使用。
我想知道的是如何更好地build/architect这些库。
ins如下:
- 库仅供内部使用(意味着不在其他应用程序中发布或使用,但
projects
文件夹中的应用程序)
- 库有不同的依赖关系,如
lodash
和 RxJs
- 一个库可以在其内部导入另一个库
到目前为止我做了什么:
- 在每个库的
ng-package.json
中指定 umdModuleIds
。
- 在
lodash
和 RxJs
等外部库中指定 peerDependencies
- 设置我的应用程序构建,其中包含
prebuild
约 5 个命令 ng build lib-name
通过“&&” 组合
- 我用下一种方式导入 Lodash
import { cloneDeep } from 'lodash'
现在我看到我的 main.js
块比将一些 services/components/functions 提取到外部库之前大得多。现在 main.js
的产品构建大小为 2.1 Mb,在我看来这太大了。
此外,我不确定是否值得为每个库(UMD、FESM2015、FESM5)制作 3 个不同的版本。
我按照下一个表格 import { LibService } from 'lib'
.
的文档中的建议从 dist 文件夹导入库
Nrwl 工具,由 Angular 核心贡献者开发,专门用于企业架构,包括单存储库。
Nrwl nx-examples 是一个很好的入门资源。
我开始使用 nx
来构建一个新项目。最后,我的项目结构如下:
platform-directory/
|
---apps/
| |
| ---app1/
| |
| ---app2/
|
---library1/
| |
| ---src/
|
---library2/
| |
| ---src/
|
---angular.json
|
---package.json
|
---README.md
|
---tsconfig.json
tsconfig.json
顶层 tsconfig.json
应包含应用程序和库的大部分全局配置以及 paths
快捷方式(如果需要)。
路径快捷方式可以配置如下:
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"baseUrl": "./",
"declaration": false,
"downlevelIteration": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"module": "esnext",
"moduleResolution": "node",
"sourceMap": true,
"target": "es6",
"lib": [
"es2018",
"dom"
],
"paths": {
"@app1*": [
"./apps/app1/src/app*"
],
"@lib1/package1": [
"./lib1/src/package1/public_api.ts"
],
"@lib1/package2": [
"./lib1/src/package2/public_api.ts"
],
...
}
库导入
在应用程序中,可以直接从库源导入库代码,例如:
import { MyLibraryComponent } from '@lib1/package1'
由于您没有发布库,因此无需构建它们。当您 运行 在您的应用程序代码上编译 Angular 时,库代码将根据需要自动包含和优化。
重要提示: 在每个库中,不要使用路径快捷方式导入文件,因为这会导致 hard-to-debug 循环依赖。例如,在 lib2
中可以使用:
import { MyLibraryComponent } from '@lib1/package1'
但是,如果在 lib1
中使用此导入,则会产生循环依赖。
作为旁注,每个应用程序都会有一个 tsconfig.app.json
和 tsconfig.spec.json
,如下所示:
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc/apps/app1"
},
"include": [
"src/**/*.ts"
],
"exclude": [
"test.ts",
"**/*.spec.ts"
]
}
特别是关于您对包大小的担忧:我怀疑 Lodash 是其中的罪魁祸首。尝试使用 lodash-es
代替,并仅从您需要的包中导入。例如
import cloneDeep from 'lodash-es/cloneDeep';
这应该会大大减少您的捆绑包中 lodash
的数量,但它仍然不会像大多数用例那样小。我专门为此创建了一个名为 micro-dash
. For example it includes cloneDeep
, which as the docs 的库,说将 397 bytes
添加到您的包中(大致 - 这取决于多个因素),而 lodash 版本添加 12,289 bytes
.
不过,最终,要对超大包进行故障排除,您应该确切地看到每个库向其中添加了多少。那就是source-map-explorer
的境界。绝对 运行 在你的最终产品包中,首先解决最严重的问题!
我的 Angular monorepo 项目中有几个应用程序。我还编写了大约 5 个库以在应用程序中使用。
我想知道的是如何更好地build/architect这些库。
ins如下:
- 库仅供内部使用(意味着不在其他应用程序中发布或使用,但
projects
文件夹中的应用程序) - 库有不同的依赖关系,如
lodash
和RxJs
- 一个库可以在其内部导入另一个库
到目前为止我做了什么:
- 在每个库的
ng-package.json
中指定umdModuleIds
。 - 在
lodash
和RxJs
等外部库中指定 - 设置我的应用程序构建,其中包含
prebuild
约 5 个命令ng build lib-name
通过“&&” 组合
- 我用下一种方式导入 Lodash
import { cloneDeep } from 'lodash'
peerDependencies
现在我看到我的 main.js
块比将一些 services/components/functions 提取到外部库之前大得多。现在 main.js
的产品构建大小为 2.1 Mb,在我看来这太大了。
此外,我不确定是否值得为每个库(UMD、FESM2015、FESM5)制作 3 个不同的版本。
我按照下一个表格 import { LibService } from 'lib'
.
Nrwl 工具,由 Angular 核心贡献者开发,专门用于企业架构,包括单存储库。
Nrwl nx-examples 是一个很好的入门资源。
我开始使用 nx
来构建一个新项目。最后,我的项目结构如下:
platform-directory/
|
---apps/
| |
| ---app1/
| |
| ---app2/
|
---library1/
| |
| ---src/
|
---library2/
| |
| ---src/
|
---angular.json
|
---package.json
|
---README.md
|
---tsconfig.json
tsconfig.json
顶层 tsconfig.json
应包含应用程序和库的大部分全局配置以及 paths
快捷方式(如果需要)。
路径快捷方式可以配置如下:
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"baseUrl": "./",
"declaration": false,
"downlevelIteration": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"module": "esnext",
"moduleResolution": "node",
"sourceMap": true,
"target": "es6",
"lib": [
"es2018",
"dom"
],
"paths": {
"@app1*": [
"./apps/app1/src/app*"
],
"@lib1/package1": [
"./lib1/src/package1/public_api.ts"
],
"@lib1/package2": [
"./lib1/src/package2/public_api.ts"
],
...
}
库导入
在应用程序中,可以直接从库源导入库代码,例如:
import { MyLibraryComponent } from '@lib1/package1'
由于您没有发布库,因此无需构建它们。当您 运行 在您的应用程序代码上编译 Angular 时,库代码将根据需要自动包含和优化。
重要提示: 在每个库中,不要使用路径快捷方式导入文件,因为这会导致 hard-to-debug 循环依赖。例如,在 lib2
中可以使用:
import { MyLibraryComponent } from '@lib1/package1'
但是,如果在 lib1
中使用此导入,则会产生循环依赖。
作为旁注,每个应用程序都会有一个 tsconfig.app.json
和 tsconfig.spec.json
,如下所示:
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc/apps/app1"
},
"include": [
"src/**/*.ts"
],
"exclude": [
"test.ts",
"**/*.spec.ts"
]
}
特别是关于您对包大小的担忧:我怀疑 Lodash 是其中的罪魁祸首。尝试使用 lodash-es
代替,并仅从您需要的包中导入。例如
import cloneDeep from 'lodash-es/cloneDeep';
这应该会大大减少您的捆绑包中 lodash
的数量,但它仍然不会像大多数用例那样小。我专门为此创建了一个名为 micro-dash
. For example it includes cloneDeep
, which as the docs 的库,说将 397 bytes
添加到您的包中(大致 - 这取决于多个因素),而 lodash 版本添加 12,289 bytes
.
不过,最终,要对超大包进行故障排除,您应该确切地看到每个库向其中添加了多少。那就是source-map-explorer
的境界。绝对 运行 在你的最终产品包中,首先解决最严重的问题!