如何使用 Bazel 将 Angular 应用程序集成到 Monorepo 中?

How to Integrate an Angular Application into a Monorepo with Bazel?

过去几周我一直在构建一个 Typescript monorepo,它可以使用 Bazel 构建并部署到 Kubernetes。但最后一个难题是 将 Angular 应用程序 集成到整个工作流程中,这让我非常头疼。

项目

 ├── WORKSPACE
 ├── BUILD.bazel
 ├── package.json
 ├── packages
 │   ├── package1
 │   ├── package2
 │   └── package3
 └── services
     ├── service1
     ├── service2
     ├── service3
+    └── angular-app

Source code

目标

最后,我希望能够为 Angular 应用程序添加 k8s_object 到根 BUILD.bazel 文件,如下所示:

 load("@io_bazel_rules_k8s//k8s:objects.bzl", "k8s_objects")
 k8s_objects(
     name = "kubernetes_deployment",
     objects = [
         "//services/service1",
         "//services/service2",
         "//services/service3",
+        "//services/angular-app"
     ]
)

它应该在我 运行 bazel run :kubernets_deployment.apply 时将 Angular 应用程序部署到 Kubernetes。就像其他已经完美运行的服务一样。部署过程涉及:

挑战

  1. 将 Angular Bazel 依赖项添加到我现有的 WORKSPACE 文件
  2. 可以通过 import { something } from '@project/package1';
  3. 将我的本地 packages 导入我的 Angular 源代码
  4. 所有 NPM 依赖项都应添加到根 package.json 而不是 Angular 项目中的
  5. 集成 NgRx(我的 Angular 应用使用 NgRx 进行状态管理)
  6. 集成 Angular Universal(用于服务器端呈现)
  7. 集成 Angular PWA(渐进式网络应用程序)
  8. 设置本地开发服务器

我试过的

rules_nodejs Angular 例子

我很惊讶地发现了一个类似于我的项目的工作示例:https://github.com/bazelbuild/rules_nodejs/tree/master/examples/angular。但事实证明,他们的 monorepo 的结构有些不同。他们还使用 scss,我不是,也没有集成 NgRx 或 Angular Universal。所以我试着用它作为模板,但我无法让它工作。

带有 Angular CLI 的 Bazel

当然,我也尝试了将 Bazel 添加到 Angular 的记录方式:https://angular.io/guide/bazel,这似乎适用于一个干净的项目。使用 ng build --leaveBazelFilesOnDisk 可以访问 Bazel 文件。但是我收到错误消息,告诉我找不到 NgRx 和我的本地包。


更新

我已经完成了在干净的 angular 项目上设置所有内容的第一步:https://github.com/flolu/cents-ideas/tree/4d444240cbbe2f8b015c4b7c85746c473bc6842b/services/client 但是我收到一个我无法解决的错误:

ERROR: /home/flolu/Desktop/cents-ideas/services/client/src/app/BUILD.bazel:5:1: Compiling Angular templates (Ivy - prodmode) //src/app:app failed (Exit 1)
external/npm/node_modules/@angular/router/router.d.ts:2421:22 - error NG6002: Appears in the NgModule.imports of AppRoutingModule, but could not be resolved to an NgModule class.

This likely means that the library (@angular/router) which declares RouterModule has not been processed correctly by ngcc, or is not compatible with Angular Ivy. Check if a newer version of the library is available, and update if so. Also consider checking with the library's authors to see if the library is expected to be compatible with Ivy.

2421 export declare class RouterModule {
                          ~~~~~~~~~~~~
external/npm/node_modules/@angular/router/router.d.ts:2421:22 - error NG6003: Appears in the NgModule.exports of AppRoutingModule, but could not be resolved to an NgModule, Component, Directive, or Pipe class.

This likely means that the library (@angular/router) which declares RouterModule has not been processed correctly by ngcc, or is not compatible with Angular Ivy. Check if a newer version of the library is available, and update if so. Also consider checking with the library's authors to see if the library is expected to be compatible with Ivy.

2421 export declare class RouterModule {
                          ~~~~~~~~~~~~
external/npm/node_modules/@angular/platform-browser/platform-browser.d.ts:44:22 - error NG6002: Appears in the NgModule.imports of AppModule, but could not be resolved to an NgModule class.

This likely means that the library (@angular/platform-browser) which declares BrowserModule has not been processed correctly by ngcc, or is not compatible with Angular Ivy. Check if a newer version of the library is available, and update if so. Also consider checking with the library's authors to see if the library is expected to be compatible with Ivy.

44 export declare class BrowserModule {
                        ~~~~~~~~~~~~~
src/app/app-routing.module.ts:11:14 - error NG6002: Appears in the NgModule.imports of AppModule, but itself has errors

11 export class AppRoutingModule { }

Florian,到目前为止进步很大:)

我建议仔细查看该 angular 示例中与 bazel 相关的文件,并将所有需要的规则/函数复制到您的项目中。这些文件是 .bazelrcWORKSPACEBUILD.bazel(在每个子文件夹中)、rules_docker.patch(它应用于 WORKSPACE 中的 http_archive)。

此外,/src 文件夹中有几个非常重要的文件(它们在 BUILD 文件中使用):rollup.config.jsrxjs_shims.jsmain.dev.tsmain.prod.ts. example 文件夹中有两个 index.html 文件:一个用于生产,一个用于开发。

顺便说一句,这个例子已经包含了 ngrx,所以它可能很适合你,只需仔细查看 BUILD 文件中的 ng_module 规则及其依赖项。只需在此处添加您的部门(如 @npm//@ngrx/store 等)。

至于Angular Universal,貌似现在Bazel支持的还不是很好。这是要跟踪的问题:https://github.com/bazelbuild/rules_nodejs/issues/1126

至于 scss,如果你使用简单的 css,那很好,然后你可以将它插入到 ng_moduleassets 字段中,你不需要不需要从 rules_sass (sass_binary, sass_library) 添加额外的编译步骤。从示例中复制规则时忽略它们。

关于项目结构,这里是我从Nx迁移到Bazel的例子:https://github.com/scalio/nx-bazel-starter。 它有点过时,所以最好以官方为导向。但您可能会在那里找到一些有用的功能,即文件夹在 Nx 中的结构。其实这个想法和你的非常相似:他们只是将服务称为应用程序,将包称为库并共享公共 package.json.