User Interfaces & Micro Frontends — Chia UI theo team (BMS)

Mở đầu
Backend tách thành microservices răm rắp, vậy còn cái frontend thì sao? Đây là mảng ít được nhắc tới nhất khi nói về microservices, nhưng cũng là chỗ nhiều hệ thống "vỡ" nhất: mọi service đằng sau đều gọn gàng, còn UI thì vẫn là một khối SPA duy nhất ôm hết tất cả. Chương 14 của Building Microservices dành trọn cho câu hỏi này — làm sao ghép UI lại khi dữ liệu đã nằm rải rác ở nhiều service, và khi nào nên theo đuổi micro frontends.
Ảnh: César Gaviria — Pexels
UI monolith — cái "backend cũ" trốn trong frontend
Khi tách backend, nhiều team quên mất một điều: cái SPA đang gọi thẳng vào tất cả service vẫn là một khối nguyên khối đúng nghĩa. Nó không có database dùng chung, nhưng nó là nơi duy nhất mà mọi luồng nghiệp vụ phải đi qua — muốn đổi gì ở UI là phải phối hợp với đủ mọi team, deploy phải nhịp nhàng với nhau. Hệ quả là Conway's Law trả thù: cấu trúc team không đổi, thì chỗ nghẽn chỉ dời từ backend qua frontend.
Cái khó nằm ở chỗ UI không giống backend. Một service có thể tự do chọn tech stack và deploy độc lập, nhưng một trang web thì phải hiển thị nhất quán — màu sắc, font, cách tương tác — dù dữ liệu đến từ đâu. Nên câu chuyện ở chương này không phải "có nên tách UI không", mà là "tách tới mức nào và ghép bằng cách gì".
Page-level composition — bắt đầu từ thứ đơn giản nhất
Kiểu composition đầu tiên và đơn giản nhất: mỗi trang do một service render trọn vẹn, các trang nối với nhau bằng link thường. Trang chủ thuộc team A, trang chi tiết sản phẩm thuộc team B, người dùng đi từ trang này sang trang kia như đi từ website này sang website khác. Không có gì phức tạp, không cần cơ chế ghép nào, mỗi team tự do làm trang của mình.
Cách này ăn ngay khi ranh giới trang trùng với ranh giới nghiệp vụ — mỗi trang chỉ cần dữ liệu từ một service. Nhưng đời không đơn giản vậy: trang giỏ hàng cần thông tin từ cả service sản phẩm lẫn service thanh toán, layout header/footer thì ai cũng dùng. Khi một trang phải "pha trộn" dữ liệu từ nhiều nơi, page-level composition bắt đầu lộ giới hạn — kéo theo reload trang nhiều, trải nghiệm rời rạc, và team phải thương lượng với nhau về từng pixel.
Ảnh: Tranmautritam — Pexels
Server-side composition — ghép mảnh ngay ở biên
Bước tiếp theo là để server hoặc edge ghép giúp. Ý tưởng giống include trang con hồi xưa: mỗi service trả về một mảnh HTML (fragment) cho phần mình phụ trách, rồi một tầng trung gian — server hoặc CDN edge — ráp các mảnh đó lại thành trang hoàn chỉnh trước khi gửi về trình duyệt. Hai kỹ thuật kinh điển là SSI (Server Side Includes) và ESI (Edge Side Includes).
Điểm mạnh của cách này là performance và sự đơn giản: edge cache được từng fragment riêng lẻ, phần nào ít đổi thì cache lâu, phần nào động thì cache ngắn; trình duyệt chỉ nhận một trang HTML hoàn chỉnh nên không phải lo về việc tải nhiều bundle. Nó hợp với nội dung thiên về đọc, ít tương tác — tin tức, trang sản phẩm, dashboard đọc dữ liệu. Hạn chế là những tương tác phức tạp phía client vẫn khó xử lý triệt để ở tầng này.
Widget-level composition — micro frontends
Kiểu cuối cùng là để trình duyệt tự ghép: mỗi service phục vụ một "widget" — một phần UI kèm logic riêng — và trang web tổng hợp chúng lại ở phía client bằng JavaScript (hoặc iframe). Đây chính là micro frontends: chia một UI lớn thành nhiều phần deploy độc lập, mỗi phần gắn với một team và một business capability cụ thể.
Điểm hấp dẫn của micro frontends nằm ở chỗ nó kéo nguyên tắc của microservices lên tận UI: team sở hữu trọn một "lát cắt" từ database tới màn hình, tự chọn framework (team này React, team kia Vue cũng được, miễn là khớp ở "đường nối"), và deploy UI của mình mà không cần chờ ai. Đây là cách duy nhất để cái lợi deploy độc lập của microservices không dừng lại ở backend. Nhưng cái giá cũng không nhỏ: trình duyệt phải tải nhiều bundle hơn, trải nghiệm giữa các widget dễ lệch nhau, và việc test luồng xuyên qua nhiều widget phức tạp hơn hẳn.
Ảnh: Ann H — Pexels
Khi nào nên dùng — và những cạm bẫy dễ gặp
Điểm quan trọng nhất mà chương này nhấn mạnh: micro frontends không phải đích đến bắt buộc. Nếu team nhỏ, sản phẩm thay đổi UI không quá dồn dập, thì một team sở hữu trọn UI vẫn là lựa chọn hợp lý nhất. Chỉ khi lợi ích deploy độc lập thật sự lớn hơn chi phí vận hành — nhiều team cùng đụng vào UI, chu kỳ release khác nhau — thì mới đáng bước sang client-side composition.
Nếu đã đi theo hướng này, có mấy cạm bẫy cần né. Một là over-fragment: ranh giới micro frontend phải theo business capability và ranh giới team, không phải theo từng component nhỏ — tách càng mịn thì ghép càng đau. Hai là consistency: nhiều team làm UI khác nhau thì UX dễ loạn, nên cần design system dùng chung (design tokens, component library). Nhưng cẩn thận — shared UI library cũng giống shared code: nếu ai cũng phải nâng cấp theo nhau thì nó thành coupling point mới, đúng kiểu "shared kernel" mà ai cũng sợ. Ba là performance: nhiều bundle JavaScript nghĩa là nhiều request và nhiều dung lượng hơn, phải tính chuyện lazy load và cache ở edge ngay từ đầu.
Key Takeaways
- UI là mắt xích cuối cùng hay bị bỏ quên khi tách microservices — nếu không xử lý, UI monolith trở thành điểm nghẽn mới đúng theo Conway's Law.
- Ba kiểu composition xếp theo độ phức tạp tăng dần: page-level (link thường), server-side (SSI/ESI ghép ở biên), client-side (micro frontends, trình duyệt tự ghép).
- Micro frontends mang deploy độc lập lên tận UI, nhưng đi kèm chi phí: performance, accessibility, consistency giữa các widget.
- Design system giúp giữ UI đồng nhất, nhưng shared component library dễ thành coupling point nếu không có governance rõ ràng.
- Bắt đầu từ cách đơn giản nhất, nâng cấp dần theo nhu cầu thật — đừng chạy theo trend.
Glossary
| UI composition | Cách ghép giao diện từ nhiều service khác nhau thành một trang hoàn chỉnh. |
| Page-level composition | Mỗi trang do một service render trọn vẹn, các trang nối với nhau bằng link. |
| Server-side composition | Server hoặc edge ghép các fragment HTML từ nhiều service trước khi trả về trình duyệt. |
| Edge Side Includes (ESI) | Kỹ thuật cho phép edge cache ghép nhiều fragment HTML từ nhiều nguồn khác nhau. |
| Micro frontends | Chia UI thành nhiều phần deploy độc lập, mỗi phần gắn với một team/business capability. |
| Client-side composition | Trình duyệt ghép UI từ nhiều fragment (JS bundle, iframe) tải từ các service khác nhau. |
| Design tokens | Các biến thiết kế dùng chung (màu, spacing, typography) giúp giữ UI nhất quán giữa các team. |
| Conway's Law | Tổ chức tạo ra hệ thống có cấu trúc phản chiếu cách tổ chức đó giao tiếp với nhau. |
Kết
UI là nơi Conway's Law thể hiện rõ nhất: tách backend mà không đụng tới frontend thì team vẫn phải phối hợp quanh một khối duy nhất, chỉ là khối đó dời từ database lên màn hình. Chương này không hề ép "nhất định phải micro frontends" — ngược lại, lộ trình được gợi ý là đi từ page-level, thêm server-side composition khi trang cần dữ liệu từ nhiều service, và chỉ bước sang client-side khi lợi ích deploy độc lập thật sự đáng giá. Chương tiếp theo của cuốn sách chuyển sang góc nhìn tổ chức và con người — nơi mọi quyết định kiến trúc cuối cùng đều bị chi phối bởi cách team vận hành.