Files
Edu/apps/parent-portal/next.config.js
SpecialX 96a936e154 feat(parent-portal): docker 构建修复 + 禁用 mock + 记录下游待办
Dockerfile 改用 standalone 模式

next.config.js 添加 output standalone

修复 cssnano-simple 构建失败:globals.css 注释含 */ 被误解析

tailwind.config.js 覆盖 boxShadow 为 rgba 格式 + 禁用 ringWidth

组件修复:替换 / 语法为 inline style 或自定义类

otel.ts 添加 webpackIgnore 跳过 optionalDependencies 静态分析

.env.example 默认禁用 mock

新增 .dockerignore 和 docs/nextstep.md

删除 postcss.config.js

验证:Docker 镜像构建成功,容器 healthy,typecheck + lint 零错误
2026-07-13 17:21:39 +08:00

96 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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 GraphQLurql
// Bundle 分析P6-3 性能优化ANALYZE=true 时启用)
const withBundleAnalyzer =
process.env.ANALYZE === "true"
? require("@next/bundle-analyzer")({ enabled: true })
: (config) => config;
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,
// standalone 输出模式:自包含 server.js + 精简 node_modules适合 Docker 部署)
output: "standalone",
// 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 = withBundleAnalyzer(nextConfig);