// parent-portal next.config.js // Module Federation Remote 角色(Shell = teacher-portal :4000) // 当 NEXT_PUBLIC_MF_ENABLED=enabled 时启用 MF;否则作为独立 Next.js 应用运行 // // 依据: // - 02-architecture-design.md §1.2 MF 配置 // - ARB-002 MF Shell 暴露清单 // - F10 MF 暴露粒度(AppShell 整体) // - F9 GraphQL(urql) const NextFederationPlugin = process.env.NEXT_PUBLIC_MF_ENABLED === "enabled" ? require("@module-federation/nextjs-mf") : null; const remotes = (isServer) => ({ teacher: `teacher_app@http://localhost:4000/_next/static/${isServer ? "ssr" : "chunks"}/remoteEntry.js`, }); /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, // ESM 兼容(MF 2.0 需要) experimental: { externalDir: true, }, // 安全头(F-安全硬化,复用 Shell 配置) async headers() { return [ { source: "/(.*)", headers: [ { key: "X-Frame-Options", value: "SAMEORIGIN" }, { key: "X-Content-Type-Options", value: "nosniff" }, { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" }, { key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()", }, ], }, ]; }, // API 代理:/api/v1/* → api-gateway async rewrites() { return [ { source: "/api/v1/:path*", destination: `${process.env.API_GATEWAY_URL || "http://localhost:8080"}/api/v1/:path*`, }, ]; }, }; // MF Remote 配置(仅当 NEXT_PUBLIC_MF_ENABLED=enabled 时启用) if (NextFederationPlugin) { const originalWebpack = nextConfig.webpack; nextConfig.webpack = (config, options) => { config.plugins.push( new NextFederationPlugin({ name: "parent_app", filename: "static/chunks/remoteEntry.js", remotes: remotes(options.isServer), exposes: { "./pages": "./src/pages", "./ChildSwitcher": "./src/components/ChildSwitcher", }, shared: { react: { singleton: true, requiredVersion: "^18.3.0" }, "react-dom": { singleton: true, requiredVersion: "^18.3.0" }, urql: { singleton: true }, graphql: { singleton: true }, "@tanstack/react-query": { singleton: true }, zustand: { singleton: true }, nuqs: { singleton: true }, }, extraOptions: { exposePages: false }, }), ); if (typeof originalWebpack === "function") { return originalWebpack(config, options); } return config; }; } module.exports = nextConfig;