Micro-frontend Learning
Bắt đầu

Bắt đầu

Chuẩn bị môi trường và dựng ví dụ host/remote nhỏ nhất.

Bạn đã hiểu vì sao một phần frontend có thể cần phát hành riêng, nhưng khi mở terminal thì bắt đầu từ đâu? Nếu dựng ngay cả shell, catalog và cart với routing, shared state và pipeline, bạn sẽ khó biết lỗi đầu tiên đến từ môi trường, cấu hình tải module hay chính nghiệp vụ.

Nhóm Bắt đầu đi theo một lát cắt nhỏ hơn: chuẩn bị máy, thống nhất bài toán shop, tạo workspace, rồi để shell tải một module catalog và render nó. Mình ưu tiên nhìn rõ đường đi từ build đến browser trước khi thêm luồng giỏ hàng.

Site tài liệu và workspace thực hành là hai project khác nhau

Repository hiện tại là site Next.js + Fumadocs, không chứa ứng dụng shop chạy sẵn. Bài Cấu trúc workspace hướng dẫn bạn tạo shop-workspace riêng, đặt bên cạnh repo tài liệu. Chạy npm run dev tại gốc repo tài liệu chỉ mở site docs, không chạy host/remote.

Các bài Chuẩn bị môi trường, Bài toán shop mẫu và Cấu trúc workspace đã có nội dung chi tiết. Hai bài Host và remote đầu tiên, Chạy và kiểm tra local hiện còn là trang khung; các mốc tích hợp dưới đây mô tả mục tiêu học, không khẳng định đã có lab hoàn chỉnh.

Mục lục

Mục tiêu của nhóm bài

Kết quả đầu tiên không phải một shop đầy đủ tính năng. Đó là một shell render được UI do catalog cung cấp qua một ranh giới tích hợp rõ ràng, và bạn chỉ ra được request nào đã tải code ấy.

Sau khi hoàn thành các bài trong nhóm, bạn nên làm được những việc sau:

  • Chọn đúng Node.js, package manager và dùng DevTools để kiểm tra request, status và lỗi JavaScript.
  • Giải thích trách nhiệm của shell, catalog và cart trong shop mẫu, không bắt đầu từ việc chia mỗi component thành một remote.
  • Chạy và build từng app trong workspace mà không import source nội bộ của app khác.
  • Phân biệt app chạy standalone với app đã expose module để host consume.
  • Kiểm tra bằng cả UI và Network rằng shell đang tải catalog từ build của remote.

Có một giới hạn cần giữ rõ: host tải remote thành công ở local chưa chứng minh deploy độc lập ở production. Bạn còn cần artifact được publish đúng, cơ chế chọn phiên bản, contract tương thích và đường khôi phục khi bản mới có lỗi. Nhóm này chỉ giúp bạn hiểu và kiểm chứng cơ chế tích hợp đầu tiên.

Kiến thức và công cụ cần chuẩn bị

Nếu chưa phân biệt được micro-frontend với việc tách component, hãy đọc Nền tảng trước. Nếu đã hiểu bài toán nhưng chưa quen bundler, bạn vẫn có thể bắt đầu; chỉ cần biết build tạo ra JavaScript/CSS để browser tải và chạy.

Kiến thứcBạn sẽ dùng ở đâu
import, export và import()Hiểu public module và thao tác tải bất đồng bộ có thể thất bại
Component, props và lifecycle cơ bản của ReactRender UI catalog trong shell ở bước Federation
Script trong package.json và working directoryChạy đúng app, cài dependency vào đúng workspace
URL, port, origin và HTTP statusPhân biệt sai địa chỉ remote với lỗi module hoặc lỗi render
Console và Network trong DevToolsTìm bằng chứng thay vì chỉ đổi cấu hình cho tới khi hết lỗi

Toolchain của nhóm đã được chọn trong các bài chi tiết: Node.js 22, npm workspaces và webpack 5. Bài workspace bắt đầu bằng JavaScript thuần để kiểm tra ba app standalone; React và Module Federation được thêm ở mốc tiếp theo. Giữ lựa chọn này khi học lần đầu để không phải debug cả khác biệt giữa các bundler.

Bạn có thể kiểm tra terminal trước khi tạo workspace:

node --version
npm --version
git --version

Với quy ước Node của lab, kết quả đầu tiên cần thuộc major 22, dạng v22.x.y; số patch phụ thuộc bản bạn cài. Đây là kiểm tra toolchain, không phải bước khởi động shop. Nếu terminal chưa tìm được lệnh hoặc đang chọn Node khác, làm theo Chuẩn bị môi trường trước.

Chưa cần Docker, Kubernetes, backend hay tài khoản cloud. Dữ liệu shop ban đầu là mock; các công cụ đó không giúp bạn phân biệt một request tải module bị 404 với một component render lỗi.

Mô hình shop và lát cắt đầu tiên

Shop mẫu có ba phạm vi trách nhiệm, nhưng không cần tích hợp cả ba cùng lúc:

PhầnTrách nhiệmCó mặt trong mốc tích hợp đầu không
ShellKhung giao diện, navigation và vùng ghép nội dungCó, đóng vai trò host
CatalogHiển thị, tìm và lọc sản phẩmCó, bắt đầu bằng một module UI nhỏ
CartQuản lý thao tác giỏ và cung cấp trạng thái cho consumerChưa ghép; app standalone được chuẩn bị trong workspace

Ở bước đầu, một vùng catalog hiển thị được trong shell là đủ. Bạn chưa cần nút “Thêm vào giỏ” hoạt động hoặc badge đồng bộ. Các yêu cầu ấy vẫn thuộc Bài toán shop mẫu, nhưng được triển khai sau khi đường tải module đã rõ.

Shell và host khác nhau thế nào

Shell là vai trò trong kiến trúc trải nghiệm: giữ layout, navigation và ghép các phần. Host là vai trò trong tích hợp Federation: consume module từ build khác. Trong ví dụ này, app shell làm cả hai việc; hai thuật ngữ không phải lúc nào cũng đồng nghĩa.

Remote là build cung cấp module công khai cho consumer. App catalog có trang standalone không có nghĩa nó đã là remote dùng được: vẫn cần khai báo module expose và cấu hình để host tải đúng container entry.

Mình giữ shell mỏng ở bước này. Nếu shell import store nội bộ của catalog hoặc tự giữ toàn bộ logic sản phẩm, bạn có thể render được UI nhưng chưa có một boundary đáng duy trì.

Browser tải code từ đâu

Đường tải dự kiến của ví dụ webpack Federation tối thiểu là:

direction: right
browser: Browser
shell: "localhost:3000\nHTML và JavaScript shell"
catalog: "localhost:3001\nContainer entry và chunks\ncatalog"
consume: "Shell consume public module"
ui: "Catalog UI trong trang shell"
browser -> shell
browser -> catalog
shell -> consume
catalog -> consume -> ui
Browserlocalhost:3000HTML và JavaScript shelllocalhost:3001Container entry và chunkscatalogShell consume public moduleCatalog UI trong trang shell
Browserlocalhost:3000HTML và JavaScript shelllocalhost:3001Container entry và chunkscatalogShell consume public moduleCatalog UI trong trang shell
Browser tải code từ đâu

Browser tải code remote và chạy nó trong trang shell; Node.js chủ yếu chạy tooling và dev server trong ví dụ này. Đây không phải việc server shell gọi trang HTML của catalog rồi nhúng nguyên trang ấy.

Với cấu hình webpack Federation thường dùng trong lab, container entry được đặt tên remoteEntry.js. Entry cho runtime biết cách lấy module được expose; code triển khai module có thể nằm ở các chunk khác. Vì vậy, một request entry thành công chưa đủ chứng minh module đã tải và render được.

Hai app vẫn có thể dùng chung DOM, CSS và JavaScript runtime của trang host. Remote không tự tạo isolation như iframe, cũng không tự trở thành security boundary. Bạn sẽ học cách xử lý ảnh hưởng chéo ở các nhóm sau.

Thứ tự đọc và thực hành

Đi theo thứ tự này để mỗi bài loại bớt một nhóm nguyên nhân gây lỗi trước khi thêm bước mới:

Thứ tựBàiKết quả cần giữ lại
1Chuẩn bị môi trườngToolchain dùng được; biết kiểm tra server từ terminal và browser
2Bài toán shop mẫuRanh giới trách nhiệm, quy tắc giỏ hàng và tiêu chí nghiệm thu đã rõ
3Cấu trúc workspaceBa app standalone, script và artifact riêng trong shop-workspace
4Host và remote đầu tiênMục tiêu: thêm React và Federation để shell consume một module catalog
5Chạy và kiểm tra localMục tiêu: kiểm tra UI, request tải module và phân biệt các loại lỗi

Hai mốc cuối cần hướng dẫn chi tiết bổ sung ở trang tương ứng. Bạn vẫn có thể hoàn thành phần chuẩn bị và workspace hiện có mà không tự suy đoán cấu hình Federation từ trang tổng quan này.

Đừng bỏ bài toán shop chỉ vì chưa làm cart ở mốc đầu. Nó giúp bạn biết phần nào phải giữ public contract và phần nào là implementation nội bộ. Nhưng cũng đừng biến toàn bộ tiêu chí nghiệm thu của shop thành điều kiện cho lần tải remote đầu tiên; hai mốc có phạm vi khác nhau.

Quy ước local cần giữ nhất quán

Các đường dẫn và port dưới đây khớp bài workspace. Chúng là quy ước của lab, không phải yêu cầu bắt buộc của micro-frontend:

App trong shop-workspacePackage npmURL local
apps/shell@shop/shellhttp://localhost:3000
apps/catalog@shop/cataloghttp://localhost:3001
apps/cart@shop/carthttp://localhost:3002

Tên package dùng để chọn workspace bằng npm; nó không tự quyết định alias Federation, tên container hay URL entry. Khi thêm tích hợp, các tên ấy cần được khai báo và đối chiếu riêng.

Đừng nhầm site docs với shell

Site Next.js hiện tại cũng mặc định dùng port 3000. Trước khi chạy shell, dừng server docs hoặc chuyển docs sang port khác. Kiểm tra cả thư mục terminal lẫn nội dung trang; mở được localhost:3000 chưa chứng minh bạn đang xem shop.

Giữ hostname localhost nhất quán, thay vì trộn với 127.0.0.1. Khác port là khác origin; điều đó ảnh hưởng request và cấu hình trình duyệt, nhưng không có nghĩa mọi cách tải remote đều cần cùng một cấu hình CORS. Hãy kiểm tra loại request thực tế trước khi sửa header.

Kiểm chứng từng mốc

Mốc workspace standalone

Sau khi đã tạo đủ file và cài tooling theo bài workspace, mở ba terminal tại root shop-workspace và chạy lần lượt:

Terminal 1
npm run dev:shell
Terminal 2
npm run dev:catalog
Terminal 3
npm run dev:cart

Mỗi URL phải hiển thị đúng heading: Shop shell, Shop catalog, Shop cart. Sau đó, npm run build tại root workspace phải tạo output riêng trong apps/*/dist. Đừng tìm output trên disk chỉ vì dev server mở được; dev server có thể phục vụ asset từ memory.

Đây là thành công của workspace, chưa phải Federation. Cấu hình ở mốc này chưa tạo remoteEntry.js, nên việc URL đó trả 404 không phải lỗi cần sửa bằng CORS hay cache.

Mốc host tải remote

Khi đã thêm cấu hình Federation ở bài tích hợp, kiểm tra cả kết quả hiển thị lẫn nguồn code:

  1. Mở shell và xác nhận vùng catalog xuất hiện bên trong trang shell, không chỉ trên trang standalone của catalog.
  2. Trong Network, đối chiếu URL container entry với server catalog; kiểm tra response là JavaScript đúng, không phải HTML fallback dù status là 200.
  3. Kiểm tra các chunk được tải tiếp và Console để xác nhận không còn lỗi tải module hoặc render.
  4. Review import của shell: module catalog đi qua public request Federation, không qua đường dẫn ../../catalog/src/... hay package đóng implementation catalog vào build shell.
  5. Dừng server catalog rồi reload shell để quan sát lần tải mới thất bại ở đâu. Nếu code đã được tải vào tab, dừng server không tự xóa module đang có trong memory.

Ở mốc này, thử dừng remote nhằm hiểu loại lỗi tải, chưa phải kiểm thử resilience hoàn chỉnh. Loading, fallback, Error Boundary và retry cần được thiết kế cụ thể; không suy ra shell đã chịu lỗi tốt chỉ vì các phần được build riêng.

Những việc chưa cần làm

Mình chưa thêm nhiều framework, global event bus hay shared store ở bước đầu. Mỗi thứ tạo thêm một đường phụ thuộc cần hiểu, trong khi câu hỏi đang cần trả lời chỉ là “shell có tải đúng module catalog không?”.

Việc để sauVì sao chưa cầnNhóm đọc tiếp
Ghép cart và đồng bộ badgeCần command, snapshot và owner của state rõ ràngGiao tiếp và trạng thái
Tạo mọi shared packageChưa có đủ consumer và public API để biết cần chia sẻ gìContracts giữa các frontend
Thêm nhiều frameworkLàm tăng bài toán lifecycle, dependency và toolingUI và framework
Cấu hình CDN, version và rollbackCần artifact và đường tích hợp đã kiểm chứng trướcTriển khai
SSR hoặc federation trong Next.jsLà mô hình tích hợp khác với lab React client-side nàyNext.js và SSR

Next.js của site tài liệu không phải lý do để chọn Next.js cho lab. Ngược lại, webpack trong lab cũng không phải lựa chọn bắt buộc cho mọi hệ thống. Giữ một stack nhất quán ở đây để học cơ chế; so sánh cách tích hợp khi bạn đã biết những gì cần kiểm chứng.

Khi bị kẹt thì kiểm tra ở đâu

Trước khi đổi config, hãy ghi lại URL đang mở, lệnh đã chạy, request thất bại đầu tiên và lỗi Console liên quan. Bốn thông tin ấy thường giúp khoanh vùng tốt hơn một ảnh trang trắng.

Dấu hiệuKiểm tra đầu tiên
Missing script: dev:shellBạn đang ở shop-workspace đã tạo theo bài workspace, hay ở repo docs?
EADDRINUSEPort có đang bị site docs hoặc process khác chiếm không?
Catalog standalone cũng không mởServer catalog đã chạy và compile thành công chưa?
Entry trả 404Đã tới mốc Federation chưa; URL, port và tên file có khớp cấu hình không?
Entry trả 200 nhưng vẫn lỗiResponse có đúng JavaScript không; chunk tiếp theo có tải được không?
Module tải được nhưng UI không renderPublic module key, kiểu export/import và lỗi React có khớp nhau không?
UI hiện được nhưng không thấy request remoteCó đang bundle source catalog vào shell, hoặc code đã tải/cache từ trước không?

Không mặc định coi mọi lỗi cross-origin là CORS. Sai port, server chưa chạy, HTML fallback và chunk tải sai base URL có biểu hiện khác nhau; Network sẽ cho bạn biết nên kiểm tra hướng nào trước. Khi cần đi sâu, dùng Debug checklist và Remote không tải được.

Checklist trước khi đi tiếp

Bạn có thể dùng checklist này để tự đánh giá sau khi hoàn thành cả phần chuẩn bị lẫn phần tích hợp:

  • Phân biệt được repo docs và shop-workspace, biết mỗi lệnh phải chạy ở đâu.
  • Toolchain nhất quán giữa các terminal; biết app nào dùng port nào.
  • Shell, catalog và cart chạy standalone, build ra artifact riêng.
  • Giải thích được tại sao standalone chưa đồng nghĩa với remote đã expose module.
  • Shell render catalog qua public module, không import implementation nội bộ.
  • Chỉ ra được request entry và chunk của catalog trong browser.
  • Phân biệt lỗi server, tải module và render; hiểu vì sao dừng remote không xóa code đã tải.
  • Không xem kết quả local là bằng chứng đủ cho isolation hay independent deployment ở production.

Bước tiếp theo

Nếu mới bắt đầu, mở Chuẩn bị môi trường rồi làm tiếp theo bảng lộ trình. Nếu đã hoàn thành workspace standalone, mốc tiếp theo là tích hợp một module catalog; chưa cần mở rộng cart để làm ví dụ đầu tiên trông giống shop hoàn chỉnh.

Khi đã kiểm chứng được đường tải module, đọc nhóm Kiến trúc và ranh giới để đánh giá cách chia domain, rồi nhóm Module Federation để hiểu sâu exposes, remotes và dependency sharing.

On this page