Angular 8:使用库构建 monorepo 应用程序的更好方法

Posted

技术标签:

【中文标题】Angular 8:使用库构建 monorepo 应用程序的更好方法【英文标题】:Is there a better way to build an Angular monorepo app with libraries? 【发布时间】:2019-12-01 21:36:21 【问题描述】:

我的 Angular monorepo 项目中有几个应用程序。此外,我还编写了大约 5 个库以供跨应用程序使用。

我想知道的是如何更好地构建/架构这些库

ins如下:

    库仅供内部使用(意味着除了projects 文件夹中的应用外,不得在其他应用中发布或使用) 库具有不同的依赖关系,例如 lodashRxJs 一个库可以在其内部导入另一个库

到目前为止我做了什么:

    在每个库的ng-package.json 中指定umdModuleIds。 在lodashRxJs 等外部库上指定peerDependencies 设置我的应用构建,其中包含 prebuild 和大约 5 个命令 ng build lib-name 通过“&&”组合 我用下一种方式导入 Lodash import cloneDeep from 'lodash'

现在我看到我的main.js 块比将一些服务/组件/函数提取到外部库之前要大得多。现在main.js 在 prod build 上的大小是 2.1 Mb,在我看来这太大了。

另外,我不确定是否值得为每个库(UMD、FESM2015、FESM5)制作 3 个不同的版本。

我按照文档中的建议从 dist 文件夹导入库,遵循下一个表单 import LibService from 'lib'

【问题讨论】:

nx.dev 可能就是您要找的。​​span> 【参考方案1】:

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 编译器时,库代码将自动包含并根据需要进行优化。

重要提示:在每个库中,不要使用路径快捷方式导入文件,因为这会导致难以调试的循环依赖关系。例如,在lib2 内可以使用:

import  MyLibraryComponent  from '@lib1/package1'

但是,如果在 lib1 中使用此导入,则会创建循环依赖。

附带说明一下,每个应用都会有一个tsconfig.app.jsontsconfig.spec.json,如下所示:


  "extends": "../../tsconfig.json",
  "compilerOptions": 
    "outDir": "../../dist/out-tsc/apps/app1"
  ,
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ]

【讨论】:

有没有比重构现有项目更简单的方法来改善这种情况? 将其标记为正确的解决方案,因为它的整体理念,虽然它很难分配给我已经有一个设置项目的情况,这会导致没有人想要的重构:D 您现在可以在没有 Nrwl 的情况下使用 Angular CLI 完成上述所有工作 - 工作区项目、多个应用程序、多个库、tscongfig 路径等。我知道 Nrwl 添加的不止这些,但它也是一个额外的构建管理框架【参考方案2】:

特别是关于您对捆绑包大小的担忧:我怀疑 Lodash 是其中的罪魁祸首。尝试改用lodash-es,并仅从您需要的包中导入。例如

import cloneDeep from 'lodash-es/cloneDeep';

这应该会大大减少捆绑包中 lodash 的数量,但它仍然不会像大多数用例那样小。为此,我专门制作了一个名为micro-dash 的库。例如,它包含cloneDeep,就像the docs 所说的将397 bytes 添加到您的捆绑包中(大致 - 它取决于多种因素),而 lodash 版本添加了12,289 bytes

不过,最终,要对超大包进行故障排除,您应该确切地看到每个库添加了多少。那是source-map-explorer 的领域。绝对在您的最终产品包上运行它,并首先解决最严重的违规者!

【讨论】:

以上是关于Angular 8:使用库构建 monorepo 应用程序的更好方法的主要内容,如果未能解决你的问题,请参考以下文章

带有库的 rush setup angular monorepo

在 GitHub Actions 工作流程中未使用语义发布-monorepo 找到存储库

AWS Codebuild:Monorepo和多个版本?

使用具体(旧)Angular 版本创建 NX Monorepo

Angular Monorepo 与 Basehref 共享资产

如何使用 Heroku 上的库部署 monorepo