Assist_Design/apps/portal/next.config.mjs

143 lines
4.3 KiB
JavaScript
Raw Normal View History

2025-08-22 17:02:49 +09:00
/* eslint-env node */
import bundleAnalyzer from "@next/bundle-analyzer";
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === "true",
});
import path from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
/** @type {import('next').NextConfig} */
const nextConfig = {
// Enable standalone output only for production deployment
output: process.env.NODE_ENV === "production" ? "standalone" : undefined,
2025-08-22 17:02:49 +09:00
// Ensure workspace packages are transpiled correctly
transpilePackages: ["@customer-portal/domain", "@customer-portal/validation"],
// Tell Next to NOT bundle these server-only libs
serverExternalPackages: [
"pino",
"pino-pretty",
"pino-abstract-transport",
"thread-stream",
"sonic-boom",
// Avoid flaky vendor-chunk resolution during dev for small utils
"tailwind-merge",
],
// Turbopack configuration (Next.js 15.5+)
// Note: public turbopack options are limited; aliasing is handled via tsconfig/webpack resolutions
// Environment variables validation
env: {
NEXT_PUBLIC_API_BASE: process.env.NEXT_PUBLIC_API_BASE,
NEXT_PUBLIC_APP_NAME: process.env.NEXT_PUBLIC_APP_NAME,
NEXT_PUBLIC_APP_VERSION: process.env.NEXT_PUBLIC_APP_VERSION,
},
// Image optimization
images: {
remotePatterns: [
{
2025-08-22 17:02:49 +09:00
protocol: "https",
hostname: "**",
},
],
},
// Disable ESLint blocking during production builds to avoid CI/CD failures
eslint: {
ignoreDuringBuilds: true,
},
// Security headers
async headers() {
return [
{
// Apply security headers to all routes
2025-08-22 17:02:49 +09:00
source: "/(.*)",
headers: [
{
2025-08-22 17:02:49 +09:00
key: "X-Frame-Options",
value: "DENY",
},
{
2025-08-22 17:02:49 +09:00
key: "X-Content-Type-Options",
value: "nosniff",
},
{
2025-08-22 17:02:49 +09:00
key: "Referrer-Policy",
value: "strict-origin-when-cross-origin",
},
{
2025-08-22 17:02:49 +09:00
key: "X-XSS-Protection",
value: "1; mode=block",
},
// Content Security Policy - allows Next.js inline scripts/styles
{
2025-08-22 17:02:49 +09:00
key: "Content-Security-Policy",
value: [
"default-src 'self'",
// Next.js requires unsafe-inline for hydration scripts
"script-src 'self' 'unsafe-inline' 'unsafe-eval'",
// Next.js/Tailwind requires unsafe-inline for styles
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"font-src 'self' data:",
// Allow API connections (include localhost for development)
// Allow localhost in development for API calls to BFF
`connect-src 'self' https: ${process.env.NODE_ENV === "development" ? "http://localhost:*" : ""}`,
"frame-ancestors 'none'",
].join("; "),
2025-08-22 17:02:49 +09:00
},
],
},
2025-08-22 17:02:49 +09:00
];
},
// Production optimizations
compiler: {
// Remove console.logs in production
2025-08-22 17:02:49 +09:00
removeConsole: process.env.NODE_ENV === "production",
},
// Experimental flags
experimental: {
externalDir: true,
optimizePackageImports: ["@heroicons/react", "lucide-react", "@tanstack/react-query"],
},
webpack(config) {
const workspaceRoot = path.resolve(__dirname, "..", "..");
config.resolve.alias = {
...config.resolve.alias,
"@customer-portal/domain": path.join(workspaceRoot, "packages/domain"),
"@customer-portal/validation": path.join(workspaceRoot, "packages/validation/src"),
};
const preferredExtensions = [".ts", ".tsx", ".mts", ".cts"];
const existingExtensions = config.resolve.extensions || [];
config.resolve.extensions = [...new Set([...preferredExtensions, ...existingExtensions])];
config.resolve.extensionAlias = {
...(config.resolve.extensionAlias || {}),
".js": [".ts", ".tsx", ".js"],
".mjs": [".mts", ".ts", ".tsx", ".mjs"],
};
config.module.rules.push({
test: /packages\/domain\/.*\.js$/,
type: "javascript/esm",
});
return config;
},
// Keep type checking enabled; monorepo paths provide types
typescript: { ignoreBuildErrors: false },
// Prefer Turbopack; no custom webpack override needed
};
export default withBundleAnalyzer(nextConfig);