SSG renders raw HTML after a while
Unanswered
Basset Bleu de Gascogne posted this in #help-forum
Basset Bleu de GascogneOP
Hi!
Been struggling with this the whole day. On mobile, after going to other apps and coming back after a while to Chrome, my app just becomes raw HTML. Not on PC, just mobile. Doesn't seem to be an issue on my device.
I'm pretty sure it has something to do with revalidating data because it won't break instantly. I have set revalidation to 60 s, slugs are SSG'd.
I thought it may be some funny business with Cloudflare caching, but I have had it happen once when running locally.
Using App Router and latest Next.js version.
Been struggling with this the whole day. On mobile, after going to other apps and coming back after a while to Chrome, my app just becomes raw HTML. Not on PC, just mobile. Doesn't seem to be an issue on my device.
I'm pretty sure it has something to do with revalidating data because it won't break instantly. I have set revalidation to 60 s, slugs are SSG'd.
I thought it may be some funny business with Cloudflare caching, but I have had it happen once when running locally.
Using App Router and latest Next.js version.
3 Replies
Basset Bleu de GascogneOP
It's 3 am here, I'll return to debugging when I've gotten a few hours of sleep. If there are any tips meanwhile, I'd be happy to have them
I can replicate the issue 100% of time on mobile. Going to the site https://alpha.kampuslounas.fi/tamk and opening other tabs on chrome to fill your device's ram and being in then for few mins and returning to the site
Basset Bleu de GascogneOP
I have narrowed down the issue to
[slug]/page.tsx
actions/fetchMenu.ts
generateStaticParams
. Removing this fixes my app, but of course removes SSG which I would like to have on my app. Am I using it correctly? I have menus on my routes, and I want to revalidate them every 60 sec.[slug]/page.tsx
import { notFound } from "next/navigation";
import RestaurantCard from "@/components/RestaurantCard";
import { fetchMenuDataServer } from "../actions/fetchMenu";
const allowedSlugs = ["tamk"];
export async function generateStaticParams() {
return allowedSlugs.map((slug) => ({
slug: slug,
}));
}
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
// check if slug is invalid
if (!allowedSlugs.includes(slug)) {
notFound();
}
const menuData = await fetchMenuDataServer(slug);
if (!menuData) {
notFound();
}
return <div>help</div>;
// return (
// <div className="m-5 mx-auto max-w-7xl">
// {menuData ? (
// <RestaurantCard menu={menuData.menu} days={menuData.days} />
// ) : (
// <p>Menu not available</p>
// )}
// </div>
// );
}
actions/fetchMenu.ts
"use server";
import sanitizeHtml from "sanitize-html";
import { MenuResponse } from "@/types";
import { fillMissingDays } from "@/utils/dayHelpers";
const fetchUrls: Record<string, string> = {
tamk: "https://fi.jamix.cloud/apps/menuservice/rest/haku/menu/97603/1?lang=fi",
arvo: "https://fi.jamix.cloud/apps/menuservice/rest/haku/menu/93077/5?lang=fi",
};
export async function fetchMenuDataServer(campusId: string) {
const url = fetchUrls[campusId];
if (!url) return null;
const res = await fetch(url, { cache: "force-cache" });
if (!res.ok) return null;
const data = (await res.json()) as MenuResponse[];
// sanitize the ingredients of all menu items (HTML)
const sanitizedData = data.map((menuResponse) => {
menuResponse.menuTypes.forEach((menuType) => {
menuType.menus.forEach((menu) => {
menu.days.forEach((day) => {
day.mealoptions.forEach((mealOption) => {
mealOption.menuItems = mealOption.menuItems.map((item) => {
if (!item.ingredients) return item;
const sanitizedIngredients = sanitizeHtml(item.ingredients, {
allowedTags: ["b", "i", "em", "strong", "p", "ul", "li", "ol"],
allowedAttributes: {},
});
return { ...item, ingredients: sanitizedIngredients };
});
});
});
});
});
return menuResponse;
});
// dates can be mnissing, so fill them in
const firstMenu = sanitizedData[0];
const rawDays = firstMenu.menuTypes[0].menus[0].days.map(({ weekday, date }) => ({
weekday,
date,
}));
const processedDays = fillMissingDays(rawDays);
return {
menu: firstMenu,
days: processedDays,
};
}