fix: production stabilization (middleware routing + docker paths)
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🏗️ Build (push) Successful in 12m46s
Build & Deploy / 🚀 Deploy (push) Successful in 20s
Build & Deploy / 🩺 Smoke Test (push) Failing after 3s
Build & Deploy / 🔔 Notify (push) Successful in 7s
Nightly QA / 🔍 Static Analysis (push) Successful in 2m36s
Nightly QA / 🔗 Links & Deps (push) Successful in 2m13s
Nightly QA / 🎭 Lighthouse (push) Successful in 3m47s
Nightly QA / 📝 E2E (push) Successful in 4m28s
Nightly QA / 🔔 Notify (push) Has been skipped
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🏗️ Build (push) Successful in 12m46s
Build & Deploy / 🚀 Deploy (push) Successful in 20s
Build & Deploy / 🩺 Smoke Test (push) Failing after 3s
Build & Deploy / 🔔 Notify (push) Successful in 7s
Nightly QA / 🔍 Static Analysis (push) Successful in 2m36s
Nightly QA / 🔗 Links & Deps (push) Successful in 2m13s
Nightly QA / 🎭 Lighthouse (push) Successful in 3m47s
Nightly QA / 📝 E2E (push) Successful in 4m28s
Nightly QA / 🔔 Notify (push) Has been skipped
This commit is contained in:
@@ -75,7 +75,7 @@ WORKDIR /app
|
|||||||
|
|
||||||
# Copy standalone output and static files (Monorepo paths)
|
# Copy standalone output and static files (Monorepo paths)
|
||||||
# Note: Base image already handles the non-root user and basic env
|
# Note: Base image already handles the non-root user and basic env
|
||||||
COPY --from=builder --chown=1001:65533 /app/apps/web/public ./apps/web/public
|
COPY --from=builder --chown=1001:65533 /app/apps/web/public ./public
|
||||||
COPY --from=builder --chown=1001:65533 /app/apps/web/.next/standalone ./
|
COPY --from=builder --chown=1001:65533 /app/apps/web/.next/standalone ./
|
||||||
COPY --from=builder --chown=1001:65533 /app/apps/web/.next/static ./apps/web/.next/static
|
COPY --from=builder --chown=1001:65533 /app/apps/web/.next/static ./apps/web/.next/static
|
||||||
|
|
||||||
|
|||||||
@@ -46,57 +46,12 @@ const nextConfig = {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
// In Standalone mode, Next.js expects the tracing root to be the monorepo root
|
||||||
outputFileTracingRoot: path.join(dirname, '../../'),
|
outputFileTracingRoot: path.join(dirname, '../../'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const withMDX = createMDX({});
|
const withMDX = createMDX({});
|
||||||
|
|
||||||
// Execute wrappers
|
// Clean, standard wrapper application
|
||||||
let config = withPayload(withMintelConfig(withMDX(nextConfig)));
|
// Rewrites are now handled by src/middleware.ts for maximum robustness
|
||||||
|
export default withPayload(withMintelConfig(withMDX(nextConfig)));
|
||||||
/**
|
|
||||||
* Injects our critical showcase rewrites into a resolved Next.js config object.
|
|
||||||
*/
|
|
||||||
function injectShowcaseRewrites(resolvedConfig) {
|
|
||||||
const originalRewrites = resolvedConfig.rewrites;
|
|
||||||
|
|
||||||
resolvedConfig.rewrites = async () => {
|
|
||||||
const existing = await originalRewrites?.() || [];
|
|
||||||
|
|
||||||
// Normalize existing to object pattern
|
|
||||||
const normalized = Array.isArray(existing)
|
|
||||||
? { afterFiles: existing, beforeFiles: [], fallback: [] }
|
|
||||||
: existing;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...normalized,
|
|
||||||
beforeFiles: [
|
|
||||||
...(normalized.beforeFiles || []),
|
|
||||||
// Diagnostic rule
|
|
||||||
{ source: '/robots-test', destination: '/robots.txt' },
|
|
||||||
// Showcase Assets
|
|
||||||
{ source: '/assets/:path*', destination: '/showcase/klz-cables.com/assets/:path*' },
|
|
||||||
{ source: '/wp-content/:path*', destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-content/:path*' },
|
|
||||||
{ source: '/wp-includes/:path*', destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-includes/:path*' },
|
|
||||||
{ source: '/:folder(case-studies|work|blog)/assets/:path*', destination: '/showcase/klz-cables.com/assets/:path*' },
|
|
||||||
{ source: '/:folder(case-studies|work|blog)/wp-content/:path*', destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-content/:path*' },
|
|
||||||
{ source: '/:folder(case-studies|work|blog)/wp-includes/:path*', destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-includes/:path*' },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return resolvedConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle both standard objects and functional wrappers (like withPayload)
|
|
||||||
if (typeof config === 'function') {
|
|
||||||
const originalConfigWrapper = config;
|
|
||||||
config = async (phase, args) => {
|
|
||||||
const resolved = await originalConfigWrapper(phase, args);
|
|
||||||
return injectShowcaseRewrites(resolved);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
config = injectShowcaseRewrites(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default config;
|
|
||||||
|
|||||||
53
apps/web/src/middleware.ts
Normal file
53
apps/web/src/middleware.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import type { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PRODUCTION STABILIZATION MIDDLEWARE
|
||||||
|
* This middleware handles legacy asset routing for the KLZ showcase,
|
||||||
|
* ensuring assets are correctly mapped regardless of Next.js config wrapper behavior.
|
||||||
|
*/
|
||||||
|
export function middleware(request: NextRequest) {
|
||||||
|
const { pathname } = request.nextUrl;
|
||||||
|
|
||||||
|
// 1. Diagnostic Rewrite
|
||||||
|
if (pathname === '/robots-test') {
|
||||||
|
return NextResponse.rewrite(new URL('/robots.txt', request.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Legacy Showcase Asset Mapping
|
||||||
|
// Matches: /wp-content/*, /wp-includes/*, /assets/*, and their relative subpaths
|
||||||
|
const showcaseAssetPattern = /^\/(?:wp-content|wp-includes|assets|(?:case-studies|work|blog)\/(?:wp-content|wp-includes|assets))\/(.*)/;
|
||||||
|
const match = pathname.match(showcaseAssetPattern);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const assetPath = match[0];
|
||||||
|
|
||||||
|
// Normalize path by stripping the case-studies/work/blog prefix if present
|
||||||
|
const normalizedPath = assetPath.replace(/^\/(?:case-studies|work|blog)/, '');
|
||||||
|
|
||||||
|
// Map to the literal directory in public/
|
||||||
|
// Destination: /showcase/klz-cables.com/...
|
||||||
|
return NextResponse.rewrite(new URL(`/showcase/klz-cables.com${normalizedPath}`, request.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimization: Only run middleware for legacy asset paths to minimize overhead
|
||||||
|
export const config = {
|
||||||
|
matcher: [
|
||||||
|
'/robots-test',
|
||||||
|
'/wp-content/:path*',
|
||||||
|
'/wp-includes/:path*',
|
||||||
|
'/assets/:path*',
|
||||||
|
'/case-studies/wp-content/:path*',
|
||||||
|
'/case-studies/wp-includes/:path*',
|
||||||
|
'/case-studies/assets/:path*',
|
||||||
|
'/work/wp-content/:path*',
|
||||||
|
'/work/wp-includes/:path*',
|
||||||
|
'/work/assets/:path*',
|
||||||
|
'/blog/wp-content/:path*',
|
||||||
|
'/blog/wp-includes/:path*',
|
||||||
|
'/blog/assets/:path*',
|
||||||
|
],
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user