Chào bạn! Bạn đã bao giờ phải 'đau đầu' với một ứng dụng 'khổng lồ', cồng kềnh và khó nhằn chưa? Kiểu như, mỗi lần muốn sửa một lỗi nhỏ hay thêm một tính năng mới là y như rằng phải 'đụng' vào cả một 'con quái vật' to đùng, rồi chờ đợi mỏi mòn để nó chịu 'nhả' ra bản cập nhật ấy. Đừng lo lắng nữa! Hôm nay, mình sẽ bật mí về một 'bí kíp' cực xịn giúp 'phân thây' con quái vật ấy thành những 'siêu anh hùng' nhỏ bé, nhanh nhẹn và cực kỳ 'độc lập': Kiến trúc Microfrontend! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/o2xU6u9.png' alt='Sơ đồ so sánh Monolithic và Microfrontend'> **🔍 Trọng tâm Dự án của chúng mình** Trong hành trình hiện đại hóa một hệ thống 'cổ lỗ sĩ', đội ngũ chúng mình đã quyết định 'lột xác' nó bằng cách áp dụng kiến trúc Microfrontend, đặc biệt là với Angular. Mục tiêu là gì ư? Đơn giản thôi: Biến ứng dụng từ 'một cục' thành nhiều 'mảnh ghép' nhỏ xinh, dễ quản lý hơn, khả năng mở rộng thì 'vô đối', tốc độ ra mắt tính năng mới nhanh như chớp và vẫn đảm bảo mọi thứ 'dễ dùng' cho tất cả mọi người (chuẩn mực Accessibility đó nha). **🏗️ Bối cảnh Dự án: 'Con Quái Vật' và những 'Cơn Đau Đầu'** Hãy hình dung thế này nhé: Ứng dụng cũ của chúng mình giống như một 'ngôi nhà' được xây dựng bằng một khối duy nhất (Monolithic). Mọi thứ đều dính chặt vào nhau, khiến mỗi thay đổi nhỏ cũng có thể 'rung chuyển' cả hệ thống. Điều này dẫn đến những 'cơn đau đầu' không hề nhỏ: * **Liên kết chặt chẽ:** Các phần của ứng dụng 'dính' vào nhau như keo, sửa một chỗ dễ hỏng chỗ khác. * **Triển khai dài lê thê:** Việc 'ra mắt' phiên bản mới cứ như rùa bò. * **Khó làm việc song song:** Các đội phát triển 'dẫm chân' lên nhau vì cùng làm trên một 'cục' code. * **Hiệu suất 'hụt hơi':** Đôi khi ứng dụng 'ì ạch' khi phải xử lý dữ liệu khổng lồ. **💡 Những 'Chiêu Thức' Đã Áp Dụng (Implementation Highlights)** Để giải quyết 'bài toán' này, chúng mình đã triển khai một loạt 'chiêu thức' đỉnh cao: **1. Định nghĩa 'Hợp đồng' tiêu chuẩn giữa các Microfrontend** Để các 'siêu anh hùng' Microfrontend có thể 'nói chuyện' với nhau mà không 'cãi nhau', chúng mình cần một 'ngôn ngữ chung', hay còn gọi là 'hợp đồng' (Contract) giữa chúng. Mỗi 'anh hùng' phải 'công khai' những 'khả năng' (API) của mình để người khác có thể 'nhờ vả'. Tưởng tượng như hai công ty hợp tác, họ cần có một bản hợp đồng rõ ràng về trách nhiệm và cách làm việc vậy đó! ```typescript // claims.service.ts - Shared Service in a Shared Library import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root'}) export class ClaimsService { constructor(private http: HttpClient) {} getClaimsData() { return this.http.get('/api/claims'); } submitClaim(claimData: any) { return this.http.post('/api/submit-claim', claimData); } } ``` Đoạn code trên chính là một 'hợp đồng' mẫu cho dịch vụ `ClaimsService`, giúp các Microfrontend khác 'biết' cách lấy dữ liệu khiếu nại hay gửi yêu cầu. Cứ gọi là dùng được ngay! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/mFe21aH.png' alt='Hai module giao tiếp thông qua API'> **2. Ứng dụng Shell: 'Tổng Hành Dinh' Điều Phối & Điều Hướng 'Đội Quân' Microfrontend** Tiếp theo là 'Tổng hành dinh' của chúng ta – Shell Application. Đây chính là nơi 'điều phối' và 'tập hợp' tất cả các 'siêu anh hùng' Microfrontend lại thành một ứng dụng hoàn chỉnh. Nó giống như một 'đại sảnh' lớn có nhiều cánh cửa, mỗi cánh cửa dẫn đến một 'gian hàng' (Microfrontend) riêng biệt vậy. Nhờ có Webpack Module Federation, chúng mình có thể 'tải' từng 'gian hàng' này lên một cách linh hoạt, khi cần! `webpack.config.js` trong Shell application: ```javascript module.exports = { name: 'shell', remotes: { auth: 'auth@http://localhost:4201/remoteEntry.js', dashboard: 'dashboard@http://localhost:4202/remoteEntry.js', claimsForm: 'claimsForm@http://localhost:4203/remoteEntry.js', claimsHistory: 'claimsHistory@http://localhost:4204/remoteEntry.js' }, shared: { angular: { singleton: true } } }; ``` Nhìn vào `webpack.config.js` của Shell, bạn sẽ thấy nó 'biết' được các Microfrontend `auth`, `dashboard`, `claimsForm`, `claimsHistory` đang ở đâu (`http://localhost:xxxx`). Khi người dùng truy cập, Shell sẽ 'dẫn' họ đến đúng 'gian hàng' mà họ muốn thông qua cấu hình routing bên dưới. Điều này giúp mỗi 'gian hàng' tự quản lý đường đi lối lại của mình, còn 'Tổng hành dinh' thì lo việc 'dẫn khách' thôi! `app-routing.module.ts` trong Shell Application: ```typescript const routes: Routes = [ { path: '', loadChildren: () => import('dashboard/Module').then(m => m.DashboardModule) }, { path: 'login', loadChildren: () => import('auth/Module').then(m => m.AuthModule) }, { path: 'claims-form', loadChildren: () => import('claimsForm/Module').then(m => m.ClaimsFormModule) }, { path: 'claims-history', loadChildren: () => import('claimsHistory/Module').then(m => m.ClaimsHistoryModule) } ]; ``` <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/kK3hQnU.png' alt='Shell Application điều phối các Microfrontend'> **3. Triển khai 'Nhà máy Tự động' CI/CD với Azure DevOps** Xây xong các 'siêu anh hùng' rồi thì làm sao để chúng 'ra trận' nhanh nhất đây? À ha, đó là lúc Dây chuyền Tự động Hóa CI/CD (Continuous Integration/Continuous Deployment) của Azure DevOps phát huy tác dụng! Tưởng tượng một nhà máy sản xuất tự động: code của chúng mình được 'đẩy' vào, đi qua các 'trạm' tự động kiểm tra, xây dựng và cuối cùng 'ra lò' sản phẩm hoàn chỉnh để 'triển khai' ngay lập tức. Cực kỳ nhanh và chuẩn xác luôn! `azure-pipelines.yml` đơn giản cho Shell application: ```yaml trigger: branches: include: - main pool: vmImage: 'ubuntu-latest' steps: - task: NodeTool@0 inputs: versionSpec: '16.x' displayName: 'Install Node.js' - task: Npm@1 inputs: command: 'install' displayName: 'Install Dependencies' - task: Npm@1 inputs: command: 'run build -- --prod' displayName: 'Build Angular Project' - task: AzureWebApp@1 inputs: azureSubscription: 'Your-Azure-Subscription' appName: 'your-web-app-name' package: '$(Build.ArtifactStagingDirectory)/**/*.zip' ``` Đoạn `azure-pipelines.yml` này chính là 'kịch bản' cho 'nhà máy' đó: Nó sẽ tự động cài Node.js, cài đặt các thư viện cần thiết, 'đóng gói' ứng dụng Angular và cuối cùng 'phóng' nó lên Azure. Mọi thứ cứ thế mà chạy bon bon! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/rM1j8Hw.png' alt='Sơ đồ quy trình CI/CD tự động'> **4. Docker: 'Chiếc Hộp Thần Kỳ' cho Mọi Môi Trường** Và để 'chuyến hàng' đến nơi 'an toàn' và 'ổn định' trên mọi 'địa hình' (môi trường máy chủ), chúng mình dùng đến 'chiếc hộp thần kỳ' Docker! Mỗi Microfrontend và cả Shell App đều được 'đóng gói' cẩn thận vào một 'container' Docker riêng biệt. Nghĩa là, bất kể bạn chạy ứng dụng ở đâu, nó sẽ hoạt động y hệt như trên máy bạn đã phát triển vậy. Không lo 'lỗi của máy ai' nữa nhé! `Dockerfile` mẫu cho Shell application: ```dockerfile # Use official node image as base FROM node:16 # Set working directory WORKDIR /app # Copy package.json and install dependencies COPY package*.json ./ RUN npm install # Copy the rest of the app code COPY . . # Expose the port EXPOSE 4200 # Build the Angular app and serve RUN npm run build --prod CMD ["npx", "http-server", "dist"] ``` Cái Dockerfile này giống như 'hướng dẫn đóng gói': Nó bảo Docker dùng 'nguyên liệu' Node.js, 'lắp ráp' ứng dụng Angular của chúng ta thành phiên bản 'sẵn sàng sản xuất' và 'đặt' nó vào một 'chiếc hộp' có cổng 4200. Từ giờ, cứ mang 'chiếc hộp' này đi đâu là chạy vèo vèo! <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/j1v2X5x.png' alt='Docker Containers - Đóng gói ứng dụng'> **🎯 Kết quả & Lợi ích 'Khủng'** Sau tất cả những nỗ lực ấy, kết quả là gì ư? Tuyệt vời hơn mong đợi luôn! * **Triển khai Nhanh Chóng:** Từ 'vài tuần' giờ chỉ còn 'vài ngày' là ứng dụng đã sẵn sàng 'lên sóng'. * **Phát triển Độc Lập:** Các đội dev giờ đây không còn phải 'xếp hàng' chờ nhau, mỗi đội cứ 'tung hoành' trên phần việc của mình. * **Hiệu Suất Vượt Trội:** Tải trang nhanh hơn, phản hồi mượt mà hơn – người dùng thích mê! * **Trải Nghiệm Người Dùng 'Đỉnh Của Chóp':** Giao diện và trải nghiệm được cải thiện, dễ dàng tiếp cận với mọi đối tượng. * **Bảo Trì Dễ Dàng:** Code sạch sẽ, rành mạch, 'mảnh nào ra mảnh nấy' nên việc bảo trì cũng nhẹ nhàng hơn hẳn. **👏 Lời kết: Cứu tinh của những 'Dự án Khổng Lồ'** Kiến trúc Microfrontend thực sự đã giúp chúng mình 'viết lại' định nghĩa về cách xây dựng và duy trì các ứng dụng 'khủng'. Nó đã 'trao quyền' cho các đội ngũ, giúp họ 'bay' nhanh hơn, mở rộng an toàn hơn và tập trung hoàn toàn vào trải nghiệm người dùng. Còn bạn thì sao? Dự án của bạn đã 'đón' Microfrontend về nhà chưa? Hãy chia sẻ những suy nghĩ và bài học 'xương máu' của bạn ở phần bình luận nhé! Nếu bạn muốn 'xem tận mắt' code hoặc tìm hiểu sâu hơn, đừng ngần ngại kết nối với mình nha!
Khám phá cách chúng tôi tái cấu trúc một ứng dụng cũ thành kiến trúc microfrontend hiện đại bằng Angular, Webpack Module Federation, CI/CD và Docker. Tăng tốc phát triển, cải thiện hiệu suất và mở khóa tiềm năng cho đội ngũ của bạn!