Site icon Khoa Phạm BK Blog

Nx Workspace là gì? — Giới thiệu và hướng dẫn setup monorepo từ đầu

Bắt đầu thứ Hai với ticket “thêm tính năng auth vào app” — nghe đơn giản. Nhưng project đang có: một React frontend, một Node.js API, một package shared types dùng chung, và một admin dashboard riêng. Bốn repo khác nhau. Bốn lần npm install. Bốn pipeline CI/CD. Và khi bạn update kiểu dữ liệu trong shared types, bạn phải nhớ đồng bộ thủ công sang từng repo còn lại — và thường xuyên quên.

Đây là bài toán mà Nx Workspace được sinh ra để giải quyết. Không phải chỉ là “để code vào một chỗ” — mà là biến một monorepo từ thứ nghe có vẻ phức tạp thành thứ hoạt động nhanh hơn, nhất quán hơn, và có thể scale được khi team lớn lên.

Nx là gì?

Nx là một build system và monorepo management tool mã nguồn mở, được xây dựng bởi Nrwl — công ty do hai cựu engineer của Google thành lập năm 2016. Ban đầu chỉ hỗ trợ Angular, nhưng giờ Nx hỗ trợ hầu hết mọi stack: React, Vue, Next.js, NestJS, Node.js, và ngay cả Go hay Java thông qua plugin ecosystem.

Nếu monorepo là “để tất cả dự án trong một repo” thì Nx là thứ làm cho cái repo đó thực sự hoạt động được:

Hãy hình dung Nx như một traffic controller thông minh cho codebase của bạn: nó biết chính xác project nào phụ thuộc vào project nào, task nào cần chạy trước, kết quả nào đã được cache, và chỉ chạy đúng những gì cần thiết — không hơn, không kém.

Nx khác gì Turborepo?

Câu hỏi hay gặp nhất. Cả hai đều là monorepo tool với caching và task orchestration — nhưng có sự khác biệt về triết lý:

TurborepoNx
Triết lýLightweight, ít opinionatedFull-featured, có kiến trúc rõ ràng
Code generationKhông có✅ Mạnh — generators cho mọi thứ
Plugin ecosystemHạn chế✅ 100+ official + community plugins
Project graphCơ bản✅ Interactive visualization
Phù hợp nhấtProject nhỏ, Vercel ecosystemProject vừa-lớn, cần structure
Learning curveThấp hơnCao hơn — nhưng đáng

Tóm gọn: Turborepo là high-speed engine, Nx là full vehicle sẵn sàng cho production. Nếu có 50+ package trong monorepo hoặc cần distributed execution — Nx là lựa chọn rõ ràng hơn.

Các khái niệm cốt lõi cần hiểu trước

Setup Nx Workspace từ đầu

Bước 1: Tạo workspace mới

Chạy lệnh sau và làm theo prompts:

npx create-nx-workspace@latest my-workspace

# Nx sẽ hỏi một số câu:
# ✔ Which stack do you want to use? → None (sẽ thêm sau)
# ✔ Package-based or integrated? → Integrated
# ✔ Enable Nx Cloud? → Tùy (free tier có remote cache)

cd my-workspace

Cấu trúc được tạo ra:

my-workspace/
├── apps/              ← Apps sẽ nằm ở đây
├── libs/              ← Shared libraries
├── nx.json            ← Cấu hình Nx (caching, task runners...)
├── package.json       ← Root package.json
└── tsconfig.base.json ← TypeScript path aliases dùng chung

Bước 2: Thêm React app đầu tiên

Cài plugin React và generate app:

# Cài Nx React plugin
npm install --save-dev @nx/react

# Generate React app
npx nx g @nx/react:application --name=web --directory=apps/web

# Nx sẽ hỏi:
# ✔ Bundler? → Vite (recommended) hoặc Webpack
# ✔ Stylesheet format? → CSS / SCSS / Tailwind...

Cấu trúc sau khi thêm app:

apps/
└── web/
    ├── src/
    │   ├── app/
    │   │   ├── app.tsx
    │   │   └── app.spec.tsx
    │   └── main.tsx
    ├── project.json     ← Cấu hình targets của project này
    ├── vite.config.ts
    └── tsconfig.json

Bước 3: Thêm Node.js API

# Cài Nx Node plugin
npm install --save-dev @nx/node

# Generate Node app (Express)
npx nx g @nx/node:application --name=api --directory=apps/api

# Hoặc nếu dùng NestJS
npm install --save-dev @nx/nest
npx nx g @nx/nest:application --name=api --directory=apps/api

Bước 4: Tạo shared library

Đây là phần làm cho monorepo thực sự có giá trị. Tạo một lib chứa shared TypeScript types dùng chung cho cả frontend lẫn backend:

# Tạo shared types library
npx nx g @nx/js:library --name=shared-types --directory=libs/shared/types

# Tạo shared UI components library
npx nx g @nx/react:library --name=ui --directory=libs/shared/ui

Sau khi tạo, tsconfig.base.json tự động được update với path alias:

// tsconfig.base.json
{
  "compilerOptions": {
    "paths": {
      "@my-workspace/shared-types": ["libs/shared/types/src/index.ts"],
      "@my-workspace/ui": ["libs/shared/ui/src/index.ts"]
    }
  }
}

Giờ bạn import shared code một cách sạch sẽ trong cả hai app:

// Trong React app
import { User, Order } from '@my-workspace/shared-types'
import { Button, Modal } from '@my-workspace/ui'

// Trong Node API — cùng một import path
import { User, Order } from '@my-workspace/shared-types'

Không cần publish lên npm, không cần symlink thủ công, không cần copy-paste types giữa các project. Thay đổi type một chỗ, TypeScript báo lỗi ở mọi nơi đang dùng nó ngay lập tức.

Các lệnh Nx hay dùng nhất

Chạy tasks cơ bản

# Build một project cụ thể
npx nx build web
npx nx build api

# Chạy dev server
npx nx serve web
npx nx serve api

# Chạy test
npx nx test web
npx nx test shared-types

# Chạy lint
npx nx lint web

# Chạy nhiều targets cùng lúc (parallel)
npx nx run-many -t build test --parallel=3

Affected — Chỉ chạy những gì thay đổi

Đây là tính năng tiết kiệm thời gian nhất khi dùng Nx trong CI:

# Build chỉ những project bị ảnh hưởng bởi changes hiện tại
npx nx affected -t build

# Test chỉ những project bị ảnh hưởng
npx nx affected -t test

# Lint chỉ những project bị ảnh hưởng
npx nx affected -t lint

# Xem project nào bị ảnh hưởng (không chạy gì)
npx nx affected:graph

Ví dụ thực tế: bạn sửa code trong libs/shared/types. Nx biết rằng apps/webapps/api đều import lib đó — nên nx affected -t test sẽ chạy test cho cả ba project. Nhưng nếu bạn chỉ sửa UI component trong libs/shared/ui, Nx biết API không import nó — nên chỉ test web app và ui lib, bỏ qua API hoàn toàn.

Project Graph — Visualize dependencies

# Mở interactive dependency graph trong browser
npx nx graph

Lần đầu chạy lệnh này, bạn sẽ thấy toàn bộ dependency graph của workspace hiển thị dạng interactive — click vào node để xem dependencies, filter theo project, hay focus vào một sub-graph. Đặc biệt hữu ích khi onboard member mới hoặc debug circular dependency.

Nx Cache — Không chạy lại thứ đã chạy

# Lần đầu build — chạy thật
npx nx build web
# > NX  Successfully ran target build for project web (12s)

# Lần hai — code không thay đổi → dùng cache
npx nx build web
# > NX  Successfully ran target build for project web
# [local cache] — 0ms

Cache được lưu local theo mặc định. Nếu bật Nx Cloud (có free tier), cache được share với toàn bộ team — developer A build xong, developer B chạy cùng task sẽ dùng cache của A mà không cần chạy lại.

Cấu hình nx.json quan trọng

// nx.json
{
  "defaultBase": "main",           // So sánh affected với branch nào
  "targetDefaults": {
    "build": {
      "dependsOn": ["^build"],      // Build libs trước khi build app dùng chúng
      "cache": true                 // Cache kết quả build
    },
    "test": {
      "cache": true
    },
    "lint": {
      "cache": true
    }
  },
  "namedInputs": {
    "default": ["{projectRoot}/**/*", "sharedGlobals"],
    "sharedGlobals": ["{workspaceRoot}/tsconfig.base.json"]
  }
}

Dòng "dependsOn": ["^build"] là quan trọng nhất — nó nói với Nx rằng “trước khi build app này, hãy build tất cả dependencies của nó trước”. Ký hiệu ^ có nghĩa là “các dependencies”, không phải project hiện tại.

Tích hợp CI/CD — Chỉ build những gì thay đổi

Đây là nơi Nx tỏa sáng nhất trong môi trường team. Thay vì build và test toàn bộ monorepo mỗi lần có PR, chỉ xử lý những project bị ảnh hưởng:

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]

jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0          # Cần full history để tính affected

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - run: npm ci

      # Set SHAs để Nx biết so sánh với commit nào
      - uses: nrwl/nx-set-shas@v4

      # Chỉ lint, test, build những project bị affected
      - run: npx nx affected -t lint test build --parallel=3

Kết quả thực tế: CI pipeline của một monorepo có 20 projects thường chạy trong 3-5 phút thay vì 20-30 phút — vì mỗi PR thường chỉ thay đổi 2-3 projects, không phải tất cả.

Điểm mới đáng chú ý năm 2025-2026

TypeScript Project References — Setup mới được recommend

Nx vừa ra mắt setup mới kết hợp npm/pnpm/yarn workspaces với TypeScript project references thay vì TypeScript path aliases như trước. Setup này nhanh hơn, ít tốn memory hơn, và editor support tốt hơn cho large monorepo. Đây là recommended approach cho workspace mới tạo từ 2025 trở đi.

Nx MCP Server — AI hiểu codebase của bạn

Điểm giao thoa thú vị với AI workflow: Nx MCP Server cho phép AI assistants (Claude, Cursor…) hiểu được workspace structure, project dependencies, và task configurations của bạn. Thay vì AI làm việc “mù” không biết project graph của bạn trông như thế nào, nó có full context để đưa ra gợi ý chính xác hơn.

Self-healing CI

Khi PR fail, Nx phân tích lỗi, xác định root cause, và post fix suggestion trực tiếp vào PR. Trong nhiều case, nó có thể tự commit fix luôn — CI tiếp tục chạy mà không cần developer can thiệp. Khoảng 60% broken PRs nhận được effective fix từ tính năng này.

Khi nào KHÔNG nên dùng Nx?

Nx không phải là câu trả lời cho mọi project:

Tổng kết

Nx không chỉ là “để code vào một repo” — nó là infrastructure giúp monorepo hoạt động ở tốc độ của polyrepo nhờ caching và affected commands, đồng thời giữ được tất cả lợi ích của shared code và atomic changes.

Tóm lại những gì cần nhớ:

Nếu bạn đang có 2+ project share code với nhau và đang phải sync thủ công — đó là dấu hiệu rõ nhất để thử Nx. Chạy npx create-nx-workspace@latest, dành một buổi chiều setup, và bạn sẽ thấy ngay sự khác biệt khi thay đổi shared type và toàn bộ workspace báo lỗi đúng chỗ ngay lập tức.

Chúc anh em code vui! 🚀


Tags: #nx #monorepo #workspace #react #nodejs #typescript #cicd #devops #frontend #backend

Exit mobile version