Next.js Discord

Discord Forum

Best Practice to Show Loading Indicator on Static Pages in Next.js App Dir

Unanswered
Snowshoe posted this in #help-forum
Open in Discord
SnowshoeOP
In a production-ready Next.js 15 app (using the App Router), how do you handle showing a loading indicator for static pages that don’t use async/data fetching at the top level?

Right now, my loading.tsx doesn't get triggered because the page isn't doing any await/fetch() calls. As a result, users briefly see a blank page before the content appears.

Curious what others are doing in production to make sure static or fast-rendering pages still show a loader (even briefly) to avoid a blank screen flash. Do you force suspense? Use a shell layout? Open to patterns or suggestions. ( I would not like to wrap the whole application in a template)

15 Replies

Silver Fox
I don't think there's a good way to add a loading spinner without slowing down the overall experience. Once you build and deploy the app, the static parts should be cached at a CDN, which should speed things up.
As far as I know I've never seen a webpage that has a brief white flash on the first load, just because of how browsers work.
SnowshoeOP
I am using a DotLottieReact file there . Maybe that caused the delay while it loads
Silver Fox
I see... I don't have much experience with DotLottie React but from a quick search it doesn't look like there's a common practice for delaying its loading. Claude recommends manually listening for requestIdleCallback ([developer.mozilla.org/.../requestIdleCallback](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback) — it will delay its mount until everything else has loaded) like this:
function IdleRenderer({ children }) {
  const [shouldRender, setShouldRender] = useState(false);
  
  useEffect(() => {
    if ('requestIdleCallback' in window) {
      const handle = requestIdleCallback(() => setShouldRender(true));
      return () => cancelIdleCallback(handle);
    } else {
      // Fallback for browsers without requestIdleCallback
      const timer = setTimeout(() => setShouldRender(true), 200);
      return () => clearTimeout(timer);
    }
  }, []);
  
  return shouldRender ? children : null;
}

// Usage
<div>
  <h1>Important content</h1>
  <p>More important content</p>
  <IdleRenderer>
    <ExpensiveComponent />
  </IdleRenderer>
</div>
SnowshoeOP
Could it be an issue I use redirect to navigate to the page?
Brown bear
Yes, redirect should not be used. Use <Link/>
(or useRouter)
SnowshoeOP
Yeah but i wanted to navigate user to an other page when XYZ... User basically navigation is not bcs of a user click
and useRouter would make it client, right?
Brown bear
The component, not the page itself
SnowshoeOP
Yeah but i wanted to redirect before rendering the page from page X to page Y and show loading on page Y while static page loads
Brown bear
Is redirect() happening in a server component or in a server action?
SnowshoeOP
Server component
Brown bear
Try moving it to a server action if you can, see if that fixes it. There actually seems to be a bug with it
SnowshoeOP
Or maybe I could render a client component that automatically redirects to the other page