Chuyển tới nội dung chính

Tạo module MFE mới

Sử dụng script

./scripts/create-module.sh <tên_module> <port>

# Ví dụ:
./scripts/create-module.sh partner 8095

Script sẽ tạo folder apps/<tên_module>/ với cấu trúc chuẩn.

Checklist chuẩn khi init module mới

1) Tạo module app

Tối thiểu có cấu trúc:

apps/<module-name>/
├── src/
│ ├── pages/
│ ├── services/
│ ├── types/
│ ├── schema/
│ ├── config/
│ │ └── baseApi.ts
│ ├── store/
│ │ └── index.ts
│ ├── routes/
│ │ └── index.tsx
│ ├── App.tsx
│ ├── RemoteApp.tsx
│ ├── bootstrap.tsx
│ └── main.tsx
├── vite.config.ts
├── package.json
├── tsconfig.json
├── Dockerfile
├── nginx.conf
└── docker-compose.yml
mẹo

Trong App.tsx của module, dùng ToastProvider từ @vppos/core/ui/react để đồng bộ UI toast giữa các module.

2) Đăng ký module vào registry

Thêm entry vào apps/container/src/config/mfeRegistry.ts:

newModule: {
name: "new-module",
label: "Module Mới",
basePath: "/new-module",
devPort: 8090,
envKey: "NEW_MODULE",
},

3) Khai báo route/menu trong container

Thêm vào apps/container/src/config/routes.config.ts:

{
path: "/new-module",
mfeKey: "newModule",
permission: { requiredModule: null },
menu: {
id: "new-module",
label: "Module Mới",
icon: IoSettingsOutline,
order: 60,
},
children: [
{
path: "/new-module/feature",
mfeKey: "newModule",
permission: { requiredModule: null },
menu: {
id: "new-module-feature",
label: "Tính năng",
icon: IoListOutline,
order: 1,
parentId: "new-module",
},
},
],
}

4) Cấu hình Vite Module Federation

apps/<module>/vite.config.ts:

federation({
name: "<module-name>",
filename: "remoteEntry.js",
exposes: {
"./App": "./src/RemoteApp.tsx",
},
shared: {
react: { singleton: true },
"react-dom": { singleton: true },
"react-router-dom": { singleton: true, requiredVersion: "*" },
"react-redux": { singleton: true },
},
dts: false,
});

5) Cập nhật MFE gateway của container

5.1 Nginx route cho module mới

Thêm block vào apps/container/nginx.conf:

location /new-module/ {
if ($http_accept ~* "text/html") {
rewrite ^ /index.html last;
}
set $upstream_new_module ${UPSTREAM_NEW_MODULE};
rewrite ^/new-module/(.*)$ /$1 break;
proxy_pass http://$upstream_new_module;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

5.2 Envsubst trong entrypoint

Thêm biến vào apps/container/docker-entrypoint.sh:

${UPSTREAM_NEW_MODULE}

5.3 Default upstream trong Dockerfile container

Thêm vào apps/container/Dockerfile:

ENV UPSTREAM_NEW_MODULE="new-module:8090"

6) Cập nhật docker compose

6.1 Compose local của module

apps/<module>/docker-compose.yml nên có:

  • context: .
  • dockerfile: Dockerfile
  • NODE_ENV=production
  • restart: unless-stopped
  • healthcheck tới remoteEntry.js

6.2 Compose tổng FE

Thêm service vào:

  • docker-compose.fe.yml
  • infra/docker-compose.local.yml

Và thêm vào container.depends_on nếu cần boot đồng thời.

7) Cập nhật CI/CD

Trong .gitlab-ci.yml, thêm 2 job:

  • build-<module>
  • update-<module>

Với trigger changes gồm:

  • apps/<module>/**/*
  • core/**/*

8) Cập nhật K8s manifest

Bắt buộc tạo cả 2 file:

  • infra/k8s/<module>-deployment.yaml
  • infra/k8s/<module>-service.yaml

Ví dụ service:

apiVersion: v1
kind: Service
metadata:
name: new-module-frontend-service
namespace: admin-vppos
spec:
selector:
app: new-module-frontend
ports:
- port: 8090
targetPort: 8090
type: ClusterIP

Và trong infra/k8s/container-deployment.yaml thêm env upstream:

- name: UPSTREAM_NEW_MODULE
value: "new-module-frontend-service.admin-vppos.svc.cluster.local:8090"

9) Verify nhanh trước khi merge

pnpm --filter @vppos/container dev
pnpm --filter @vppos/<module> dev

Kiểm tra:

  • route /new-module/... vào được
  • load remoteEntry.js thành công
  • không lỗi lint/build ở module và container