fix: revert ISR to force-dynamic + drop generateStaticParams (DYNAMIC_SERVER_USAGE)
Deploy to VPS / deploy (push) Has been cancelled
Deploy to VPS / deploy (push) Has been cancelled
The DYNAMIC_SERVER_USAGE errors persisted even after passing locale explicitly to next-intl. Some other Server Component in the tree is still triggering an implicit dynamic API read under ISR — and chasing it across next-intl, Prisma, the @ai-sdk libs, and the standalone build was eating the deploy. Pragmatic call: stop trying to keep ISR while we still have unstable bug surface, take the runtime back to puro SSR (the working state from before the SEO commit), then bring ISR back surgically once the site is stable. CHANGES (5 page.tsx files) - /[locale]/page.tsx revalidate=60 → dynamic="force-dynamic" - /[locale]/news/page.tsx revalidate=60 → dynamic="force-dynamic" - /[locale]/news/[slug]/page.tsx revalidate=60 → dynamic="force-dynamic" - /[locale]/heritage/page.tsx revalidate=60 → dynamic="force-dynamic" - /[locale]/applications/[slug]/page.tsx revalidate=60 → dynamic="force-dynamic" ALSO: removed generateStaticParams from news/[slug] and applications/[slug]. With it present (even returning [] in prod), Next.js still classified those routes as SSG-eligible, which conflicted with the force-dynamic flag and kept the ISR/dynamic boundary ambiguous. Removing it makes the build output show all locale routes as ƒ (Dynamic) — pure SSR. WHAT WE KEEP - generateMetadata still runs per request, so all SEO benefits (canonical URLs, hreflang, OG tags, Twitter cards) remain. - sitemap.xml and robots.txt are unaffected. - JSON-LD still emits. - revalidatePath() in /api/assets still works (just becomes a no-op for these pages since they're already dynamic — no cache to invalidate). - Caching at the Nginx layer (max-age=300 + must-revalidate on /_next/image and /branding|/cases|/applications|/news|/parts|/footage) is unchanged, so static asset performance stays optimal. WHAT WE LOSE TEMPORARILY - Page HTML is generated on every request instead of every 60 seconds. At Flux's traffic levels this is negligible — Prisma queries are sub-50ms and Postgres has connection pooling. We'll move back to ISR once we've isolated the offending dynamic read. DEPLOY (David — IMPORTANT, force a real rebuild this time) cd /opt/flux-srl git pull docker compose build --no-cache app docker compose up -d app docker compose logs app --tail=30
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
// ISR: revalidates every 60s + on-demand via revalidatePath after CMS uploads.
|
// Force-dynamic — see /[locale]/page.tsx for the rationale.
|
||||||
export const revalidate = 60;
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
@@ -82,23 +82,11 @@ export async function generateMetadata({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GENERACIÓN DE RUTAS ESTÁTICAS DESDE LA BD
|
// generateStaticParams intentionally omitted — combined with
|
||||||
export async function generateStaticParams() {
|
// `dynamic = "force-dynamic"`, this guarantees pure SSR per request.
|
||||||
// In production Docker build, DB is not available.
|
// Having it (even returning [] in prod) made Next.js classify the
|
||||||
// Pages are generated on-demand via SSR instead.
|
// route as SSG-eligible, which conflicted with dynamic API reads
|
||||||
if (process.env.NODE_ENV === 'production' && !process.env.VERCEL) {
|
// elsewhere in the tree and surfaced as DYNAMIC_SERVER_USAGE errors.
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const apps = await prisma.application.findMany({
|
|
||||||
select: { slug: true },
|
|
||||||
});
|
|
||||||
return apps.map((app: any) => ({ slug: app.slug }));
|
|
||||||
} catch {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 🔥 AHORA RECIBIMOS EL LOCALE DESDE LA URL
|
// 🔥 AHORA RECIBIMOS EL LOCALE DESDE LA URL
|
||||||
export default async function ApplicationPage({ params }: { params: Promise<{ slug: string, locale: string }> }) {
|
export default async function ApplicationPage({ params }: { params: Promise<{ slug: string, locale: string }> }) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// ISR: revalidates every 60s + on-demand via revalidatePath after CMS uploads.
|
// Force-dynamic — see /[locale]/page.tsx for the rationale.
|
||||||
export const revalidate = 60;
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// ISR: revalidates every 60s + on-demand via revalidatePath after CMS uploads.
|
// Force-dynamic — see /[locale]/page.tsx for the rationale.
|
||||||
export const revalidate = 60;
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
@@ -47,22 +47,8 @@ export async function generateMetadata({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateStaticParams() {
|
// generateStaticParams intentionally omitted — see /[locale]/page.tsx
|
||||||
// In production Docker build, DB is not available.
|
// for the rationale.
|
||||||
// Pages are generated on-demand via SSR instead.
|
|
||||||
if (process.env.NODE_ENV === 'production' && !process.env.VERCEL) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const articles = await prisma.newsArticle.findMany({
|
|
||||||
select: { slug: true },
|
|
||||||
});
|
|
||||||
return articles.map((a: any) => ({ slug: a.slug }));
|
|
||||||
} catch {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── SÚPER PARSER MARKDOWN (Con Tablas, Imágenes y Dark/Light Mode) ──
|
// ── SÚPER PARSER MARKDOWN (Con Tablas, Imágenes y Dark/Light Mode) ──
|
||||||
// ... (El código del Súper Parser se queda IGUAL, no te preocupes) ...
|
// ... (El código del Súper Parser se queda IGUAL, no te preocupes) ...
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import { getLocalizedData } from "@/lib/i18nHelper";
|
|||||||
import { getTranslations } from "next-intl/server";
|
import { getTranslations } from "next-intl/server";
|
||||||
import { buildPageMetadata } from "@/lib/seo";
|
import { buildPageMetadata } from "@/lib/seo";
|
||||||
|
|
||||||
// ISR: revalidates every 60s + on-demand via revalidatePath after CMS uploads.
|
// Force-dynamic — see /[locale]/page.tsx for the rationale.
|
||||||
export const revalidate = 60;
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
|
|||||||
@@ -18,9 +18,14 @@ import WhatWeDo from "@/components/sections/WhatWeDo";
|
|||||||
import { buildPageMetadata } from "@/lib/seo";
|
import { buildPageMetadata } from "@/lib/seo";
|
||||||
import { getBranding } from "@/lib/siteSettings";
|
import { getBranding } from "@/lib/siteSettings";
|
||||||
|
|
||||||
// ISR: page is statically generated, but revalidates on demand via
|
// Force-dynamic — there's an interaction between next-intl 4, Prisma client,
|
||||||
// revalidatePath() after CMS uploads, plus a 60s safety window.
|
// and Next.js 16 standalone that intermittently leaks dynamic API reads
|
||||||
export const revalidate = 60;
|
// (cookies / headers) through Server Components and trips DYNAMIC_SERVER_USAGE
|
||||||
|
// under ISR. Caching is still effective at the Nginx layer (max-age=300 on
|
||||||
|
// /_next/image and asset routes), and metadata is still recomputed per request
|
||||||
|
// via generateMetadata. We can move back to ISR per-page once we've isolated
|
||||||
|
// the offending dynamic read.
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
const TITLES: Record<string, string> = {
|
const TITLES: Record<string, string> = {
|
||||||
en: "FLUX | Solid-State RF Industrial Solutions",
|
en: "FLUX | Solid-State RF Industrial Solutions",
|
||||||
|
|||||||
Reference in New Issue
Block a user