Mục lục

Deployment & Release

Vận hành hệ thống MFE: CI/CD độc lập, Metadata Service và Zero-downtime Rollback.

Nguyên tắc vàng của Microfrontends: "Không bao giờ deploy Host App chỉ để cập nhật một Remote".

1. Phân tích thiết kế: Federated Deployment

Cách làm truyền thống: Monolith/Monorepo Build All

Toàn bộ dự án được build và deploy cùng một lúc vào một folder duy nhất trên Web Server.

Nhược điểm:

  • Build Time lũy tiến: Khi dự án lớn dần, dù chỉ sửa 1 dòng code, hệ thống vẫn phải re-build và re-deploy toàn bộ hàng trăm trang web.
  • Rủi ro dây chuyền (Blast Radius): Một lỗi cú pháp ở MFE A có thể làm hỏng quá trình build của cả hệ thống, khiến MFE B không thể lên Production.

Cách làm mới: Independent Pipeline (Decoupled)

Mỗi MFE sở hữu một pipeline riêng biệt. Thành phẩm là các file JS được đẩy lên S3/CDN độc lập.

Ưu điểm & Vấn đề giải quyết:

  • Time to Market: Team Catalog có thể release tính năng mới trong 5 phút.
  • Canary Releases: Có thể cấu hình để chỉ 5% người dùng nhận remote v2, trong khi 95% còn lại vẫn dùng v1 (thực hiện ở tầng Shell hoặc Load Balancer).

2. Metadata Service (Manifest)

Thay vì trỏ link cứng (http://cdn.com/remoteEntry.js), Shell App sẽ gọi một Metadata Service để lấy link động.

json:
// metadata.json (Source of Truth)
{
  "catalog": "https://cdn.shopee.vn/catalog/v2.1.0/remoteEntry.js",
  "checkout": "https://cdn.shopee.vn/checkout/v1.0.5/remoteEntry.js"
}

3. Đánh đổi (Trade-offs)

  • Cấu hình Cache phức tạp: File remoteEntry.js tuyệt đối không được cache, nhưng các file chunks phải được cache vĩnh viễn. Sai lầm ở đây sẽ dẫn đến lỗi "Loading chunk failed".
  • Version Fragmentation: Căn chỉnh phiên bản giữa các team trở nên khó khăn hơn. Cần một quy trình Quản trị (Governance) chặt chẽ.

4. Code minh họa: Pipeline CI/CD thực tế (Github Actions)

yaml:
# deploy-catalog.yml
steps:
  - name: Build MFE
    run: npm run build
  - name: Upload to S3
    run: aws s3 sync dist/ s3://shopee-assets/catalog/${{ github.sha }}/
  - name: Update Metadata Registry
    run: |
      curl -X POST https://api.shopee.vn/registry/update \
        -d '{"name": "catalog", "url": "https://cdn.shopee.vn/catalog/${{ github.sha }}/remoteEntry.js"}'

Bài tập: Remote Manifest

  • Thực hiện thiết kế một file manifest.json quản lý 3 remotes: Catalog, Auth, Order.
  • Viết 1 script (Node.js hoặc Bash) để tự động cập nhật URL mới vào file JSON này sau khi build.
  • Thử thách: Xây dựng kịch bản Rollback: Làm sao để trong vòng 30 giây có thể đưa link Catalog về version cũ mà không cần chạy lại Pipeline?

Câu hỏi phỏng vấn

Q: Chiến lược Caching tốt nhất cho remoteEntry.js là gì? Tại sao?

  • Trả lời: remoteEntry.js là file chứa thông tin trỏ tới các chunk code thực tế. Chúng ta nên đặt cache là Cache-Control: no-cache, no-store, must-revalidate. Tại sao? Vì nếu trình duyệt cache file này, khi bạn deploy bản mới, Host App sẽ vẫn đọc link của các chunk cũ, dẫn đến việc người dùng không thấy được tính năng mới. Ngược lại, các file chunk (js/css có hash) nên được cache vĩnh viễn (1 năm) để tối ưu performance.

Q: Làm sao để thực hiện Rollback một Microfrontend mà không cần build lại code?

  • Trả lời: Sử dụng Metadata Service hoặc Config Map. Thay vì dẫn link cứng tới CDN trong code, Shell App sẽ gọi một API để lấy link remoteEntry. Khi cần rollback, dev chỉ cần vào Dashboard cấu hình để API trả về link của version cũ (Vd: từ v2.1 về v2.0). Shell App sẽ tự động load code cũ mà không cần re-deploy hay downtime.

Q: "Evergreen Microfrontends" là gì? Lợi ích và rủi ro của nó?

  • Trả lời: Là chiến lược mà Remote tự update giao diện của mình trực tiếp lên Production mà không cần Host App cho phép.
    • Lợi ích: Tốc độ cực nhanh, Team Catalog fix bug là trang chủ có fix ngay.
    • Rủi ro: Nếu Remote deploy code lỗi hoặc đổi API (breaking changes), nó có thể làm sập toàn bộ trang web của Host mà Host không kịp trở tay. Giải pháp là phải có Contract TestingError Boundaries chặt chẽ.
Quảng cáo
mdhorizontal