简体   繁体   English

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

[英]Angular 8: A better way to build monorepo app with libraries

I have several apps in my Angular monorepo project.我的 Angular monorepo 项目中有几个应用程序。 Also there are about 5 libraries I've written to use across the apps.我还编写了大约 5 个库以在应用程序中使用。

What I want to know is how to better build/architect these libraries .我想知道的是如何更好地构建/架构这些库

The ins are follows: ins如下:

  1. Libraries are for internal usage only (meaning no publishing or using in other apps but those in projects folder)库仅供内部使用(意味着不能在其他应用程序中发布或使用,但在projects文件夹中的应用程序)
  2. Libraries have different dependencies like lodash and RxJs库有不同的依赖,比如lodashRxJs
  3. One library can import another inside itself一个库可以在其内部导入另一个库

What I've done so far:到目前为止我所做的:

  1. Specified the umdModuleIds in each library's ng-package.json .在每个库的ng-package.json指定了umdModuleIds
  2. Specified peerDependencies on external libraries like lodash and RxJs指定peerDependencies像外部库lodashRxJs
  3. Set up my app build which has prebuild with about 5 commands ng build lib-name combined via "&&"设置我的应用程序的构建已经prebuild约5命令ng build lib-name通过“&&”组合
  4. I import Lodash in next way import { cloneDeep } from 'lodash'我以下一种方式import { cloneDeep } from 'lodash'

Now I see that my main.js chunk is much bigger than it was before extracting some services/components/functions into external libraries.现在我看到我的main.js块比将一些服务/组件/函数提取到外部库之前大得多。 Now main.js 's size on prod build is 2.1 Mb which in my opinion is too big.现在main.js在 prod 构建上的大小是 2.1 Mb,在我看来这太大了。

Also, I'm not sure whether it's worth making 3 different builds of each library (UMD, FESM2015, FESM5).另外,我不确定是否值得为每个库(UMD、FESM2015、FESM5)制作 3 个不同的版本。

I import libraries from dist folder as it recommended in docs following next form import { LibService } from 'lib' .我按照文档中的建议从 dist 文件夹中导入库,遵循下一个表单import { LibService } from 'lib'

Nrwl tools, developed by Angular core contributors, specializes in enterprise architectures, including mono repositories. Nrwl工具由 Angular 核心贡献者开发,专门研究企业架构,包括单一存储库。

The Nrwl nx-examples is a great resource to get started. Nrwl nx-examples是一个很好的入门资源。

I started by using nx to build a new project.我开始使用nx来构建一个新项目。 In the end, my project structure ended up as follows:最后,我的项目结构如下:

platform-directory/
  |
  ---apps/
  |  |
  |  ---app1/
  |  |
  |  ---app2/
  |
  ---library1/
  |  |
  |  ---src/
  |
  ---library2/
  |  |
  |  ---src/
  |
  ---angular.json
  |
  ---package.json
  |
  ---README.md
  |
  ---tsconfig.json

tsconfig.json配置文件

The top level tsconfig.json should contain the bulk of the global configuration for the apps and libraries as well as paths shortcuts if desired.如果需要,顶级tsconfig.json应包含应用程序和库的大部分全局配置以及paths快捷方式。

Path shortcuts may be configured as follows:路径快捷方式可以配置如下:

{
  "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"
      ],
     ...
}

Library Imports图书馆进口

In the applications, library code may be imported directly from the library sources, such as:在应用程序中,可以直接从库源中导入库代码,例如:

import { MyLibraryComponent } from '@lib1/package1'

Since you are not publishing the libraries, there is no need to build them.由于您不发布库,因此无需构建它们。 When you run the Angular compiler on your application code, the library code will be automatically included and optimized as needed.当您在应用程序代码上运行 Angular 编译器时,库代码将根据需要自动包含和优化。

IMPORTANT: Within each library, do not import files using the path shortcuts, since this causes hard-to-debug circular dependencies.重要提示:在每个库中,不要使用路径快捷方式导入文件,因为这会导致难以调试的循环依赖。 For example, within lib2 it is okay to use:例如,在lib2中可以使用:

import { MyLibraryComponent } from '@lib1/package1'

However, if this import were used within lib1 , it would create a circular dependency.但是,如果在lib1中使用此导入,则会创建循环依赖项。

As a side note, each app will have a tsconfig.app.json and tsconfig.spec.json such as the following:作为旁注,每个应用程序都有一个tsconfig.app.jsontsconfig.spec.json ,如下所示:

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

Specifically regarding your concern with bundle size: I suspect Lodash is a major culprit there.特别是关于您对包大小的担忧:我怀疑 Lodash 是其中的主要罪魁祸首。 Try using lodash-es instead, and importing from only packages you need.尝试使用lodash-es ,并仅从您需要的包中导入。 Eg例如

import cloneDeep from 'lodash-es/cloneDeep';

That should reduce the amount of lodash in your bundle substantially, but it still won't be nearly as small as it could be for most use cases.这应该会大大减少包中的lodash数量,但它仍然不会像大多数用例那样小。 I made a library specifically for this reason called micro-dash .我为此专门制作了一个名为micro-dash For example it includes cloneDeep , which as the docs say adds 397 bytes to your bundle (roughly - it depends on multiple factors), whereas the lodash version adds 12,289 bytes .例如,它包括cloneDeep ,正如文档所说,它为您的包添加了397 bytes (大致 - 这取决于多种因素),而 lodash 版本添加了 12,289 12,289 bytes

Ultimately, though, to troubleshoot an oversized bundle you should see exactly how much each library is adding to it.不过,最终,要对过大的包进行故障排除,您应该确切地看到每个库向其中添加了多少。 That is the realm of source-map-explorer .这就是source-map-explorer的领域。 Absolutely run that on your final prod bundles, and address the worst offenders first!绝对在您的最终产品包上运行它,并首先解决最严重的违规者!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM