#angular #nx #monorepo #enterprise

Day 25 — Nx Monorepos: Enterprise Angular Architecture

📘 Day 25 — Nx Monorepos: Enterprise Angular Architecture

Zero to Hero — Hands-on Angular Tutorial

Today you will learn:

  • ✔️ What is a Monorepo?
  • ✔️ Why Nx is the industry standard for Angular.
  • ✔️ Creating an Nx Workspace (npx create-nx-workspace)
  • ✔️ Sharing code between apps (Libs vs Apps)
  • ✔️ The concept of Effected (nx affected:test)
  • ✔️ Architectural boundaries and best practices.

Most serious Angular jobs (Banking, Tech, Enterprise) do not use the standard ng new. They use Nx. 🏢


🟦 1. Why Nx?

The default Angular CLI is great for one app. But what if you have:

  1. Customer App (Web)
  2. Admin Portal (Web)
  3. Shared UI Library (Buttons, Inputs used by both)
  4. Shared Logic (Auth, Interfaces used by both)

If they are in separate repos, sharing code is a nightmare (npm link? private registry?). In a Monorepo, everything lives together, but is strictly isolated by libraries.

Nx Powers:

  • Caching: If you don’t change code, Nx doesn’t re-test/re-build it. Instant builds.
  • Visual Graph: See who depends on what.

🟩 2. Create an Nx Workspace

Instead of ng new, we do:

npx create-nx-workspace@latest my-org

Choices:

  • Stack: Angular
  • Monorepo or Standalone?: Integrated Monorepo (This is crucial to learn the structure).
  • Application Name: store-front
  • Bundler: Esbuild
  • Test Runner: Jest/Karma

Structure:

my-org/
  apps/
    store-front/  (The Customer App)
    store-admin/  (The Admin App)
    store-api/    (Node/Target backend, optional)
  libs/
    ui/           (Shared Buttons/Cards)
    auth/         (Shared Auth Logic)
    products/     (Product Features)
  nx.json

🟧 3. Creating a Shared Library

We never want to duplicate code. Let’s make a UI library.

nx g @nx/angular:library ui --directory=libs/shared/ui

This creates libs/shared/ui.

Add a Component to the Lib:

nx g @nx/angular:component header --project=shared-ui --export

Using the Lib in Apps: In apps/store-front/src/app/app.component.ts:

// Import directly via the path alias!
import { HeaderComponent } from '@my-org/shared/ui'; 

@Component({
  imports: [HeaderComponent],
  template: `<lib-header></lib-header>`
})
export class AppComponent {}

This works because tsconfig.base.json automatically maps @my-org/shared/ui to the folder. Valid, Intellesense-supported imports!


🟥 4. Caching & “Affected” (The Magic)

Nx knows the dependency graph.

If you modify only store-admin, and run:

nx affected:test

Nx will SKIP testing store-front entirely. It saves massive time in CI/CD.

Try the Graph:

nx graph

It opens a browser window showing exactly how your apps and libs differ and connect.


🟫 5. Enterprise Architecture Rules

How do we organize code in a huge repo?

  1. Apps should be thin: They are just containers.
  2. Libs hold the logic:
    • Feature Libs: libs/products/feature-list (Smart Components)
    • UI Libs: libs/shared/ui (Dumb Components)
    • Data Libs: libs/products/data-access (Services, State)
    • Util Libs: libs/shared/util (Date formatting, Helpers)
  3. Strict Boundaries:
    • shared cannot import from products.
    • ui cannot import from feature.
    • (Enforced via ESLint tags scope:shared, type:feature).

🎉 End of Day 25 — What You Learned

Today you graduated to “Architect”:

  • ✔️ Nx Workspace: The home for multiple apps.
  • ✔️ Apps vs Libs: Logic belongs in Libs. Apps are just shells.
  • ✔️ Path Aliases: Clean imports (@my-org/ui).
  • ✔️ Affected Commands: Only test what you break.
  • ✔️ Dependency Graph: Visualizing your architecture.

🧪 Day 25 Challenge

“Mini-Monorepo Setup”

  1. Create a new Nx workspace demo-workspace.
  2. Generate two apps: customer-app and admin-app.
  3. Generate a lib: shared-ui.
  4. Create a BannerComponent in shared-ui.
  5. Import and use the Banner in BOTH apps.
  6. Run nx serve customer-app and verify.
  7. Run nx graph and screenshot the relationship.