/** * student-portal Next.js 配置(ai14) * * MF 角色:Remote(name: 'student_app',ARB-002) * - 暴露:./StudentApp(学生端完整应用入口) * - 复用 Shell 暴露的 singleton:react/react-dom/urql/graphql/@tanstack/react-query 等 * - 独立壳模式(NEXT_PUBLIC_MF_ENABLED=false):不依赖 Shell,独立渲染 * * 端口:4001(004 §1.2 强制 4 端 4000-4003) * 路由:无 /student 前缀(student-portal_contract.md §1.2) */ const NextFederationPlugin = require('@module-federation/nextjs-mf')?.default; const isMfEnabled = process.env.NEXT_PUBLIC_MF_ENABLED === 'true'; const shellUrl = process.env.NEXT_PUBLIC_SHELL_URL || 'http://localhost:4000'; /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, // ESM 模式:transpilePackages 对齐 NestJS ESM 规范 transpilePackages: [ '@edu/ui-components', '@edu/ui-tokens', '@edu/hooks', '@edu/contracts', '@edu/shared-ts', ], async rewrites() { const gatewayUrl = process.env.NEXT_PUBLIC_API_GATEWAY_URL || 'http://localhost:8080'; return [ { source: '/api/v1/:path*', destination: `${gatewayUrl}/api/v1/:path*`, }, { source: '/api/auth/:path*', destination: `${gatewayUrl}/api/auth/:path*`, }, ]; }, // 远程类型安全:MF 加载失败不影响独立壳渲染 webpack(config, { isServer }) { // ESM 包使用 .js 后缀导入源码(TS 文件),需映射 .js → .ts // 适用于 @edu/hooks 等 ESM 包(type: module + .js 后缀导入) // 注意:仅映射 .js,不映射 .mjs(避免破坏 urql 等库的内部解析) config.resolve = config.resolve || {}; config.resolve.extensionAlias = { ...config.resolve.extensionAlias, '.js': ['.ts', '.tsx', '.js'], }; if (isMfEnabled && NextFederationPlugin) { config.plugins.push( new NextFederationPlugin({ name: 'student_app', filename: 'static/chunks/remoteEntry.js', exposes: { './StudentApp': './src/app/student-app.tsx', }, remotes: { teacher: `teacher_app@${shellUrl}/_next/static/chunks/remoteEntry.js`, }, shared: { // ARB-002 §2.2:Shell 暴露的 singleton 列表 react: { singleton: true, requiredVersion: false }, 'react-dom': { singleton: true, requiredVersion: false }, urql: { singleton: true, requiredVersion: false }, graphql: { singleton: true, requiredVersion: false }, '@tanstack/react-query': { singleton: true, requiredVersion: false, }, zustand: { singleton: true, requiredVersion: false }, nuqs: { singleton: true, requiredVersion: false }, '@edu/ui-tokens': { singleton: true, requiredVersion: false }, '@edu/ui-components': { singleton: true, requiredVersion: false, }, '@edu/hooks': { singleton: true, requiredVersion: false }, '@edu/contracts': { singleton: true, requiredVersion: false }, '@edu/shared-ts': { singleton: true, requiredVersion: false }, }, extraOptions: { exposeFiles: true, enableImageLoaderFix: true, }, }), ); } return config; }, }; module.exports = nextConfig;