The Problem

Building an Angular application with Bazel instead of the standard Angular CLI toolchain. The reference RealWorld app (a Medium.com clone called "Conduit") demonstrates CRUD, JWT auth, routing, and pagination, but its standard build setup doesn't show how to scale that to Bazel's hermetic, incremental build system. This repo is that migration, showing both build systems side by side.

What This Does

This is the standard Angular RealWorld example app (Conduit) wired for Bazel. The src/ directory holds the full application: feature modules (article, auth, editor, home, profile, settings), a core/ module for services and models, and a shared/ module for reusable components. Each feature directory carries its own BUILD.bazel file.

Bazel-specific files sit at the root: WORKSPACE, .bazelrc, .bazelignore, and a top-level BUILD.bazel. The angular.json and tsconfig.json files remain for the Angular CLI path, so both build systems coexist. The README documents both ng serve and ./node_modules/.bin/bazel run //src:prodserver.

How It Is Wired

Execution starts at src/main.ts, which bootstraps AppModule (src/app/app.module.ts). The core/index.ts barrel is the central hub: 25 modules import it, making it the highest fan-in in the app. Everything routes through ApiService (src/app/core/services/api.service.ts), which owns the outbound network calls — it defines get, put, post, and delete and is the only service that touches the HTTP layer.

The call graph shows a clean layered flow: components call feature services (UserService, ArticlesService, CommentsService), which delegate to ApiService. UserService handles auth state (setAuth, purgeAuth, attemptAuth), and JwtService manages the token in localStorage. The post function is called from 5 distinct places, the widest blast radius in the codebase. destroy (delete) is called from 3 places. No circular dependencies exist across the 81 internal modules.

How To Use It

Setup: Install dependencies with Yarn, then run the Bazel build.

yarn install
./node_modules/.bin/bazel run //src:prodserver

Configuration: The API URL lives in src/environments/environment.ts (api_url). The default points to a live backend at https://conduit.productionready.io/api.

Running it: The Angular CLI path still works — ng serve for a dev server on port 4200. The Bazel path uses the command above.

Real-World Use

A team evaluating Bazel for a large Angular codebase can use this as a reference: the BUILD.bazel files show how to declare Angular targets per feature module, and the WORKSPACE shows the external dependencies Bazel needs. The dual-build setup lets you compare incremental rebuild times between Angular CLI and Bazel on the same codebase.

Code Health & Issues

Static analysis (deterministic, not opinion) found 2 findings:

  • High — Hub module: src/app/core/index.ts has 25 dependents. Changes here have a wide blast radius. Keep it stable and small; move volatile logic out.
  • Medium — Duplicated code blocks: 7 repeated 6-line blocks across 8 files, including src/app/article/article-resolver.service.ts, src/app/home/home-auth-resolver.service.ts, and src/app/auth/no-auth-guard.service.ts. Extract shared helpers.

SDLC observations from the file structure:

  • High — No LICENSE file. Default is all rights reserved, which blocks reuse in client work. Add MIT or Apache-2.0.
  • Medium — Test coverage is thin: 2 test files against 81 source files (ratio 0.025). The README concedes "The testing part is under development."
  • Medium — No Dependabot/Renovate config. With only package.json and yarn.lock, dependency updates are manual.

The Bottom Line

A solid reference for Bazel + Angular integration, with a working dual-build setup. The codebase is the standard RealWorld app — well-structured but not novel. The missing license and thin test suite are the real blockers for production use. Suitable as a learning reference, not as a starting template without those fixes.