Implementing Full Route Caching and Revalidation at Runtime (Not Build Time) App router TS
Unanswered
Donskoy posted this in #help-forum
DonskoyOP
## 🟢 How to Implement On-Demand Incremental Static Regeneration (ISR) for the Whole App ?
I'm working on a Next.js 15 + TypeScript app using the App Router. We have three deployment stages (dev, pre-prod, prod) and a single Docker build.
### ❓ How should we handle on demand static page generation?
- No Static Generation at Build Time: npm run build should NOT fetch data
- The first request generates the page and caches it indefinitely.
- Subsequent requests serve the cached page without hitting the API.
- Pages should revalidate via an
### 🛠️ Challenges & Questions
1️⃣ How to prevent data prefetching at build time?
2️⃣ Best approach to cache full routes post-initial request?
3️⃣ How to implement /api/revalidate to refresh specific pages?
4️⃣ Is Redis beneficial for ISR in a multi-instance setup?
5️⃣ Best practices for Docker env management across all stages?
### ✅ I need something for the whole app, similar to the code implementation of ISR for dynamic routes below[(All paths at runtime)](https://nextjs.org/docs/app/api-reference/functions/generate-static-params#all-paths-at-runtime)
### Project Overview
- Stages: Development, Pre-prod, Production
- Data Source: Strapi v5 API
- Deployment: Single Docker build for all environments
🔗 Full Details : [Github](https://github.com/vercel/next.js/discussions/77139) | [V0.dev](https://v0.dev/chat/next-js-deployment-setup-HsguxXsUAAy?b=b_NAjnRiTEMrv)
I'm working on a Next.js 15 + TypeScript app using the App Router. We have three deployment stages (dev, pre-prod, prod) and a single Docker build.
### ❓ How should we handle on demand static page generation?
- No Static Generation at Build Time: npm run build should NOT fetch data
- The first request generates the page and caches it indefinitely.
- Subsequent requests serve the cached page without hitting the API.
- Pages should revalidate via an
/api/revalidate
endpoint. ### 🛠️ Challenges & Questions
1️⃣ How to prevent data prefetching at build time?
2️⃣ Best approach to cache full routes post-initial request?
3️⃣ How to implement /api/revalidate to refresh specific pages?
4️⃣ Is Redis beneficial for ISR in a multi-instance setup?
5️⃣ Best practices for Docker env management across all stages?
### ✅ I need something for the whole app, similar to the code implementation of ISR for dynamic routes below[(All paths at runtime)](https://nextjs.org/docs/app/api-reference/functions/generate-static-params#all-paths-at-runtime)
export const revalidate = 31622400;
export const dynamicParams = true;
export async function generateStaticParams() {
return [];
}
### Project Overview
- Stages: Development, Pre-prod, Production
- Data Source: Strapi v5 API
- Deployment: Single Docker build for all environments
🔗 Full Details : [Github](https://github.com/vercel/next.js/discussions/77139) | [V0.dev](https://v0.dev/chat/next-js-deployment-setup-HsguxXsUAAy?b=b_NAjnRiTEMrv)
13 Replies
Is any of this already working/in production so far?
Or are you only hypothetically asking what the outcome of implementing this structure would be?
Or are you only hypothetically asking what the outcome of implementing this structure would be?
@LuisLl Is any of this already working/in production so far?
Or are you only hypothetically asking what the outcome of implementing this structure would be?
DonskoyOP
I was asking if is there any configuration to get following results
No Static Generation at Build Time: npm run build should NOT fetch data
The first request generates the page and caches it indefinitely.
Subsequent requests serve the cached page without hitting the API.
Pages should revalidate via an /api/revalidate endpoint.
Currently, I am using
export const dynamic = "force-dynamic"; in root layout
On each request API is hit & new page is rendered
This enables me to use single docker for 3 stages with revalide api logic (Working)
my dockerfile
FROM --platform=linux/amd64 node:20-alpine AS builder
RUN apk add --no-cache libc6-compat
WORKDIR /app
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
COPY package.json package-lock.json ./
RUN npm ci --production --verbose --legacy-peer-deps
COPY . .
RUN npm run build
FROM node:20 AS runner
RUN apk add --no-cache nginx
WORKDIR /app
ENV NODE_ENV production
ENV PORT 3000
ENV HOSTNAME localhost
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY main-nginx.conf /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80 3000
CMD ["sh", "-c", "nginx && PORT=$PORT HOSTNAME=$HOSTNAME node server.js"]
No Static Generation at Build Time: npm run build should NOT fetch data
The first request generates the page and caches it indefinitely.
Subsequent requests serve the cached page without hitting the API.
Pages should revalidate via an /api/revalidate endpoint.
Currently, I am using
export const dynamic = "force-dynamic"; in root layout
On each request API is hit & new page is rendered
This enables me to use single docker for 3 stages with revalide api logic (Working)
But here we have issue server load is increased. So I need to cache / store static page on 1st request & Subsequent requests serve the cached page without hitting the API. Data doesn't change frequently from Strapi. If changed revalidate is hit
my dockerfile
FROM --platform=linux/amd64 node:20-alpine AS builder
RUN apk add --no-cache libc6-compat
WORKDIR /app
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
COPY package.json package-lock.json ./
RUN npm ci --production --verbose --legacy-peer-deps
COPY . .
RUN npm run build
FROM node:20 AS runner
RUN apk add --no-cache nginx
WORKDIR /app
ENV NODE_ENV production
ENV PORT 3000
ENV HOSTNAME localhost
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY main-nginx.conf /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80 3000
CMD ["sh", "-c", "nginx && PORT=$PORT HOSTNAME=$HOSTNAME node server.js"]
Its a POC
@LuisLl Is any of this already working/in production so far?
Or are you only hypothetically asking what the outcome of implementing this structure would be?
DonskoyOP
I’m asking hypothetically to explore what the outcome might be if we implemented this structure. No actual full fledged implementation is in place yet.
Okay, well the answer for the first two is [here in the docs](https://nextjs.org/docs/app/api-reference/functions/generate-static-params#all-paths-at-runtime)
Do something like this:
I sadly don't have any suggestions for 4️⃣ and 5️⃣.
1️⃣ How to prevent data prefetching at build time?Data won't be prefetched at build time and they'll be cached after the first time they're requested.
2️⃣ Best approach to cache full routes post-initial request?
3️⃣ How to implement /api/revalidate to refresh specific pages?Maybe call
revalidatePath()
with the specific page or slug you are trying to revalidate, send this path via searchParams
to the /api/revalidate
endpoint (/api/revalidate?pageToRevalidate=slug
) or send it via the body along with a token that authorizes the user to perform the revalidation, since API handlers are public and exposed to everyone.Do something like this:
// app/api/revalidate/route.ts
export async function POST(request: NextRequest) {
const body = await request.json();
// get the path & token
// get the token and check against it
const pathToRevalidate = // get the specific path
revalidatePath(pathToRevalidate);
return NextResponse.json({revalidated : true});
}
I sadly don't have any suggestions for 4️⃣ and 5️⃣.
@Donskoy was it helpful?
DonskoyOP
Hi @LuisLl
Sorry for the late reply, I had a small accident.
This https://nextjs.org/docs/app/api-reference/functions/generate-static-params#all-paths-at-runtime is for ISR (with dynamic route segments).
But what about page.tsx .They will be built on build time (npm run build)
If I use force-dynamic, page will be SSR. On every request new page will be returned from server. Increasing server load.
I want to make page on on demand of 1st request
Cache it & store it as static page
After 1st req, all request will be server cached static page.
Same feature as ISR but for page.tsx
Sorry for the late reply, I had a small accident.
This https://nextjs.org/docs/app/api-reference/functions/generate-static-params#all-paths-at-runtime is for ISR (with dynamic route segments).
But what about page.tsx .They will be built on build time (npm run build)
If I use force-dynamic, page will be SSR. On every request new page will be returned from server. Increasing server load.
I want to make page on on demand of 1st request
Cache it & store it as static page
After 1st req, all request will be server cached static page.
Same feature as ISR but for page.tsx
@Donskoy Hi <@744377057139753020>
Sorry for the late reply, I had a small accident.
This https://nextjs.org/docs/app/api-reference/functions/generate-static-params#all-paths-at-runtime is for ISR (with dynamic route segments).
But what about page.tsx .They will be built on build time (npm run build)
If I use force-dynamic, page will be SSR. On every request new page will be returned from server. Increasing server load.
I want to make page on on demand of 1st request
Cache it & store it as static page
After 1st req, all request will be server cached static page.
Same feature as ISR but for page.tsx
If you do not provide any params (you return [] from generateStaticParams) you won’t build any pages at build time. They’ll be generated on demand, and after that they’ll be cached
DonskoyOP
@LuisLl
Correct me if I am wrong
In Nextjs 15 App router
/app
/home
page.tsx
/products
/[id]
page.tsx <-- Uses generateStaticParams
page.tsx
layout.tsx
page.tsx
export async function generateStaticParams() {
return []; // no pre-rendered static paths on build time | all paths at run time
}
generateStaticParams is used with dynamic route segments for ISR.
Others pages don't have effect of generateStaticParams
What about home/page , products/page, root page.tsx?
Correct me if I am wrong
In Nextjs 15 App router
/app
/home
page.tsx
/products
/[id]
page.tsx <-- Uses generateStaticParams
page.tsx
layout.tsx
page.tsx
export async function generateStaticParams() {
return []; // no pre-rendered static paths on build time | all paths at run time
}
generateStaticParams is used with dynamic route segments for ISR.
Others pages don't have effect of generateStaticParams
What about home/page , products/page, root page.tsx?
@LuisLl
home/page , products/page, root page.tsx?
They will be built on build time (npm run build)
If I use force-dynamic, page will be SSR. On every request new page will be returned from server. Increasing server load.
I want to make page on on demand of 1st request
Cache it & store it as static page
After 1st req, all request will be server cached static page.
Same feature as ISR but for page.tsx
home/page , products/page, root page.tsx?
They will be built on build time (npm run build)
If I use force-dynamic, page will be SSR. On every request new page will be returned from server. Increasing server load.
I want to make page on on demand of 1st request
Cache it & store it as static page
After 1st req, all request will be server cached static page.
Same feature as ISR but for page.tsx
I see you want that behavior on your while app. Can I ask why don’t just pre-render home/page and the other ones that are similar?
I get the point for dynamic segments, where you won’t know the paths head of time but you still want to treat them as static and generate on demand the first time that route is requested, and then cached.
I get the point for dynamic segments, where you won’t know the paths head of time but you still want to treat them as static and generate on demand the first time that route is requested, and then cached.
DonskoyOP
@LuisLl
I use Strapi CMS for content.
I have 3 stages dev, stagging, prod.
Each strapi cms instance in each stage may have different content.
I have to make 3 builds - each for one stage.
To deploy Nextjs App i will be dependent on Strapi & Backend to be deployed first.
Nextjs build will be needed to be started when both strapi, backend are deployed.
Things may break when strapi, backend new build are deployed & nextjs old build is there.
There will be down time.
So, I want to create a single build which can be used in all stages.
reducing number of build pipeline, release pipeline, time and storage for new build & down time.
I use Strapi CMS for content.
I have 3 stages dev, stagging, prod.
Each strapi cms instance in each stage may have different content.
I have to make 3 builds - each for one stage.
To deploy Nextjs App i will be dependent on Strapi & Backend to be deployed first.
Nextjs build will be needed to be started when both strapi, backend are deployed.
Things may break when strapi, backend new build are deployed & nextjs old build is there.
There will be down time.
So, I want to create a single build which can be used in all stages.
reducing number of build pipeline, release pipeline, time and storage for new build & down time.