Nếu bạn đang làm việc với một monorepo dùng Nx — chẳng hạn như project với nhiều app (app-1, app-2, app-3) chia sẻ chung module core — thì chắc chắn bạn đã từng thấy dòng chữ này chạy qua terminal:
NX Running target build for project web and 3 tasks it depends on
Câu hỏi đặt ra là: Nx lấy đâu ra thông tin “3 task phụ thuộc” đó? Câu trả lời nằm ở một khái niệm cốt lõi: Project Graph.
Bài này mình sẽ giải thích Project Graph là gì, vì sao nó quan trọng, và đi qua một ví dụ cụ thể để bạn thấy Nx dùng nó như thế nào để tính toán affected projects và thứ tự thực thi task.
Project Graph là gì?
Nói đơn giản, Project Graph là một đồ thị có hướng (directed graph) mà Nx tự dựng lên bằng cách phân tích:
- Cấu trúc workspace (
project.json,package.jsoncủa từng app/lib) - Câu lệnh
importtrong source code (TypeScript/JavaScript) hoặc khai báo dependency tường minh (module Gradle, v.v. tùy plugin) - Cấu hình
implicitDependenciesnếu bạn khai báo thủ công
Mỗi node trong đồ thị là một project (app hoặc lib). Mỗi edge (cạnh) là một quan hệ phụ thuộc: “project A dùng code của project B”.
Ví dụ một workspace điển hình:

Ở đây:
web,mobile,apilà các app — thứ cuối cùng bạn build/deployui,data-access,utils,auth-apilà các lib — code dùng chung, không tự đứng một mình được- Mũi tên đi từ app xuống lib nghĩa là app đó import code từ lib
Bạn có thể tự xem đồ thị này bằng lệnh:
nx graph
Lệnh này mở một giao diện web tương tác, cực kỳ hữu ích khi workspace lớn dần và bạn không nhớ nổi ai phụ thuộc ai nữa.
Vì sao Project Graph quan trọng?
Có hai bài toán lớn mà Nx giải quyết nhờ Project Graph, và đây cũng là lý do Nx nhanh hơn hẳn so với chạy build thủ công từng project:
1. Tính toán “affected projects”
Khi bạn sửa code trong lib utils, Nx không cần bạn tự nhớ “à, utils được dùng ở web, mobile và api, phải test lại cả 3 chỗ”. Nx duyệt ngược đồ thị từ node utils, tìm mọi node có cạnh trỏ tới nó, và biết ngay:
nx affected -t test
NX Running target test for 3 projects affected by this change
web
mobile
api
Điều này cực kỳ quan trọng trong CI/CD: thay vì test toàn bộ 50 project mỗi lần commit (tốn thời gian, tốn compute), CI chỉ cần test đúng những gì thực sự bị ảnh hưởng.
2. Tính toán thứ tự thực thi task (task execution order)
Đây là phần hay nhất. Khi bạn chạy nx run web:build, Nx không chỉ build web. Nó nhìn vào Project Graph, thấy web phụ thuộc utils, data-access, ui — và phải build những cái đó trước, theo đúng thứ tự topo (topological order), nếu không web sẽ build với code lib đã lỗi thời hoặc chưa tồn tại.

Vì utils không phụ thuộc gì cả, nó luôn được build đầu tiên. data-access và ui đều chỉ phụ thuộc utils, nên chúng có thể build song song ngay sau đó. Cuối cùng, khi cả ba lib đã sẵn sàng, Nx mới build web.
Đây chính là lý do Nx gọi thứ đồ thị “runtime” này là Task Graph — về bản chất nó được suy ra từ Project Graph, cộng thêm cấu hình dependsOn trong project.json (ví dụ target build luôn phụ thuộc target build của các dependency).
Ví dụ cụ thể: khai báo dependency và xem kết quả
Giả sử trong apps/web/project.json bạn có:
{
"name": "web",
"targets": {
"build": {
"executor": "@nx/webpack:webpack",
"dependsOn": ["^build"]
}
}
}
"dependsOn": ["^build"] nghĩa là: trước khi chạy target build của web, hãy chạy target build của tất cả dependency (ký hiệu ^) trước — chính là utils, data-access, ui mà Nx đọc được từ Project Graph.
Bạn không cần tự viết utils, data-access, ui ra — Nx tự suy luận từ import trong code:
// apps/web/src/app.ts
import { formatDate } from '@myorg/utils';
import { fetchUser } from '@myorg/data-access';
import { Button } from '@myorg/ui';
Chỉ cần bạn import đúng, Project Graph sẽ tự cập nhật — không cần khai báo tay, không sợ quên.
Tổng kết
Project Graph không phải là một tính năng phụ — nó là nền tảng để Nx làm được hai việc quan trọng nhất trong một monorepo lớn: biết chính xác cái gì bị ảnh hưởng khi bạn sửa code, và biết chính xác thứ tự phải build/test cái gì trước. Nếu bạn mới bắt đầu với Nx, việc đầu tiên nên làm là chạy nx graph và nhìn kỹ workspace của mình — nhiều khi bạn sẽ phát hiện ra những dependency “ngầm” mà bản thân cũng không ngờ tới.
Bài này mình sẽ giải thích Project Graph là gì, vì sao nó quan trọng, và đi qua một ví dụ cụ thể để bạn thấy Nx dùng nó như thế nào để tính toán affected projects và thứ tự thực thi task.