feat(teacher-portal): 完整实现 teacher-portal 微前端
包含 settings/students/api、graphql、mocks、ui-tokens 设计令牌等
This commit is contained in:
@@ -1,11 +1,114 @@
|
||||
/**
|
||||
* teacher-portal Next.js 配置
|
||||
*
|
||||
* 角色:MF Shell 宿主(ARB-002 §2.3)
|
||||
* - exposes: AppShell + GraphQLProvider + 共享 hooks + 共享 UI 组件
|
||||
* - shared: react/react-dom/urql/graphql/@edu/* 设为 singleton
|
||||
* - remotes: P2 为空(NEXT_PUBLIC_MF_ENABLED=false),P3+ 逐步接入
|
||||
*
|
||||
* 维护者:ai13(teacher-portal)
|
||||
* 关联:ARB-002 §2.2 暴露清单、03-long-term-architecture.md §1.3 绞杀者模式
|
||||
*/
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
|
||||
// NextFederationPlugin 动态 require,避免构建时硬依赖(MF 2.0 在 Next 14 App Router 下按需加载)
|
||||
let NextFederationPlugin;
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
NextFederationPlugin = require("@module-federation/nextjs-mf").NextFederationPlugin;
|
||||
} catch {
|
||||
// 依赖未安装时跳过 MF 配置(如纯 typecheck 环境)
|
||||
NextFederationPlugin = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 Remote 列表(P2 为空,P3+ 按 NEXT_PUBLIC_MF_ENABLED 启用)
|
||||
*
|
||||
* ARB-002 §2.3:P2 Remote 数量 = 0,NEXT_PUBLIC_MF_ENABLED=false 默认关
|
||||
* P3 首个 Remote:student-portal(总裁 §1.3 step 4)
|
||||
*/
|
||||
function buildRemotes(isServer) {
|
||||
if (process.env.NEXT_PUBLIC_MF_ENABLED !== "true") return {};
|
||||
const chunkPath = isServer ? "ssr" : "chunks";
|
||||
return {
|
||||
student: `student_app@http://localhost:4001/_next/static/${chunkPath}/remoteEntry.js`,
|
||||
parent: `parent_app@http://localhost:4002/_next/static/${chunkPath}/remoteEntry.js`,
|
||||
admin: `admin_app@http://localhost:4003/_next/static/${chunkPath}/remoteEntry.js`,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* ARB-002 §2.2 MF Shell 暴露清单
|
||||
*/
|
||||
function buildExposes() {
|
||||
return {
|
||||
// 1. AppShell(布局 + 导航 + 认证守卫)
|
||||
"./AppShell": "./src/components/AppShell.tsx",
|
||||
// 2. GraphQLProvider(urql client 单例,总裁 §2.17 方案 A)
|
||||
"./GraphQLProvider": "./src/app/providers.tsx",
|
||||
// 3. 共享 hooks
|
||||
"./useAuth": "./packages/hooks/src/use-auth.ts",
|
||||
"./usePermission": "./packages/hooks/src/use-permission.ts",
|
||||
"./useGraphQLClient": "./packages/hooks/src/use-graphql-client.ts",
|
||||
// 4. 共享 UI 组件
|
||||
"./ErrorBoundary": "./packages/ui-components/src/error-boundary.tsx",
|
||||
"./Loading": "./packages/ui-components/src/loading.tsx",
|
||||
"./Empty": "./packages/ui-components/src/empty.tsx",
|
||||
"./RequirePermission": "./packages/ui-components/src/require-permission.tsx",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* ARB-002 §2.2 MF shared singleton 配置
|
||||
* 避免 Remote 多实例 + 缓存不一致
|
||||
*/
|
||||
function buildShared() {
|
||||
return {
|
||||
react: { singleton: true, requiredVersion: "^18.3.0" },
|
||||
"react-dom": { singleton: true, requiredVersion: "^18.3.0" },
|
||||
urql: { singleton: true, requiredVersion: "^2.2.0" },
|
||||
graphql: { singleton: true, requiredVersion: "^16.8.0" },
|
||||
"@edu/ui-tokens": { singleton: true },
|
||||
"@edu/ui-components": { singleton: true },
|
||||
"@edu/hooks": { singleton: true },
|
||||
};
|
||||
}
|
||||
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
|
||||
// ARB-002:MF Shell 配置(exposes + shared,P2 无 remotes)
|
||||
webpack(config, { isServer }) {
|
||||
if (NextFederationPlugin) {
|
||||
config.plugins.push(
|
||||
new NextFederationPlugin({
|
||||
name: "teacher_app",
|
||||
filename: "static/chunks/remoteEntry.js",
|
||||
remotes: buildRemotes(isServer),
|
||||
exposes: buildExposes(),
|
||||
shared: buildShared(),
|
||||
extraOptions: {
|
||||
exposePages: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
return config;
|
||||
},
|
||||
|
||||
// 反向代理:/api/v1/* → api-gateway :8080
|
||||
async rewrites() {
|
||||
const gateway = process.env.API_GATEWAY_URL || "http://localhost:8080";
|
||||
return [
|
||||
{
|
||||
source: '/api/v1/:path*',
|
||||
destination: `${process.env.API_GATEWAY_URL || 'http://localhost:8080'}/api/v1/:path*`,
|
||||
source: "/api/v1/:path*",
|
||||
destination: `${gateway}/api/v1/:path*`,
|
||||
},
|
||||
{
|
||||
// 登录端点(非 GraphQL,认证前提,F12: JWT 存 localStorage)
|
||||
source: "/api/auth/:path*",
|
||||
destination: `${gateway}/api/auth/:path*`,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user