High TTFB with Pages

Hi! So, there're kinda two issues here. First one is a high TTFB, averaging 500-800ms for a static Nextjs website. I tried to fix that by creating a cache rule for the website in Cloudflare. However, after I had done that, in some occassions the website returns a blank page with no content. Refreshing a couple of times sometimes returns the correct content, looks like something went wrong with caching. However, is it normal that the TTFB is so high with CF Pages without any extra caching setup?
54 Replies
Bjarn
Bjarn11mo ago
Guess it's something with the app router, if the connection is slow, the entire page is blank which I think is getting cached by some edge locations.
Bjarn
Bjarn11mo ago
I do think there's an issue here tho... CF Pages Functions (for a static site) reply really slow
Chaika
Chaika11mo ago
You're using next-on-pages or static export? Link to your site?
Bjarn
Bjarn11mo ago
Next-on-pages. I currently reenabled my cache rule so it's faster (https://spectate.net) but on the pages url it's slow: https://spectate-marketing-frontend.pages.dev/
Bjarn
Bjarn11mo ago
You can see here where I disabled the cache rule, TTFB goes through the roof. Can't remember it was like that before without the cache rule
Chaika
Chaika11mo ago
next-on-pages is special and uses a function to handle all requests. TTFB is really low with CF Pages and static assets, but this isn't just static assets
Bjarn
Bjarn11mo ago
That's what I thought too, the app itself (app.spectate.net) is a separate CF pages project, also Nextjs App Router with next-on-pages, its TTFB is quite low, total response takes 200-300ms including authentication etc. This website is just a static marketing site, it doesn't do any serverside stuff, started to happen when migrated to App Router though... so I guess that has definitely something to do with it and maaaaaybe I see something, will get back to it asap
Chaika
Chaika11mo ago
Is the site open source or any more information? I'd ask @Better James for his help if he has time, he is the resident nextjs person and maintainer of next-on-pages. Not really sure if there's enough information to go off though. Maybe something that changed recently or some known app router quirk Edit: opps, that was supposed to be a silent ping NotLikeThis could trry #next-on-pages as well
James
James11mo ago
My initial thoughts would be that your route is opted into the edge runtime and doing SSR stuff, maybe sending fetch requests that take a while to complete, before returning back to the client
Bjarn
Bjarn11mo ago
Yea I see what's happening here Before with the pages dir, I had getStaticProps() During the rewrite to App Router, I of course removed that one. But still opted in to next-on-pages due to api routes. Note: all content is static from the CMS. But I guess it's now retrieving those as I haven't set the "dynamic" property, going to try to play with that I thought it wasn't necessary as it doesn't do any fetch or other server side calls but maybe (have to check) it's because I accidentally made the root layout an async function
James
James11mo ago
Generally my view is to only opt routes into the edge runtime that need to do work on the server, otherwise leave them opted out and they'll get prerendered at build time
Bjarn
Bjarn11mo ago
Ahhh really? That's interesting, didn't know that, I just opted in everything to run on edge. Woops. Or at least the root layout, which forces sub segments to be edge too
Bjarn
Bjarn11mo ago
I know this isn't CF pages related, but, I'm getting this now (which is why I always opted in for edge). These should only get the latest content from the CMS, they also have generateStaticParams. Am I missing something here with next-on-pages?
James
James11mo ago
Yeah so with dynamic routes that get prerendered, they generate a fallback nodejs function. To avoid generating a fallback function and to only prerender routes for the ones provided in generateStaticParams, you can do export const dynamicParams = false;
Bjarn
Bjarn11mo ago
Ahhhhhhhhhhhh alright! I saw that in the docs indeed
Bjarn
Bjarn11mo ago
They're SSG now, but still complains about edge (same error as before)
Bjarn
Bjarn11mo ago
did you mean to also enable edge, no right?
James
James11mo ago
No Umm, are you sure you put the export and that you're returning paths in generateStaticParams?
Bjarn
Bjarn11mo ago
Yep :S Very similar to getStaticPaths, and if I build and run locally it does get the paths
Bjarn
Bjarn11mo ago
oh wait a sec, nope it's throwing 404's (I tested with edge still on a couple of mins ago woops) that's odd
James
James11mo ago
DD if it returns an empty array it'll try to generate a fallback function instead and ignore the route segment option saying not to 🙄
Bjarn
Bjarn11mo ago
oh dang. this change... lolsob
Bjarn
Bjarn11mo ago
Bjarn
Bjarn11mo ago
^screenshot from the Prismic docs notice the difference.. woops. I'm still using the asLink helper which was required with getStaticPaths
James
James11mo ago
smh
Bjarn
Bjarn11mo ago
The pain hahaha Aaaanyway, regarding the TTFB I found it pretty odd that the homepage (which isn't from the CMS, thus static) was so slow especially compared to my app itself which has auth etc
Bjarn
Bjarn11mo ago
Bjarn
Bjarn11mo ago
This is what I saw in the Function Metrics. The worker functions were having a hard time
James
James11mo ago
Oh my gosh
Bjarn
Bjarn11mo ago
Also received a couple of "CPU limits exceeded" errors which I never experienced with my app with auth middlewares etc. Yea that was my reaction too 😂
Bjarn
Bjarn11mo ago
For reference, this is the app ^
James
James11mo ago
Well, I've not seen someone that high before I'll be honest. I wonder if that was because it was all on the edge runtime maybe when it didnt need to be
Bjarn
Bjarn11mo ago
Hmm, the app is also on the edge router for every page since I set it in the root layout
James
James11mo ago
Then my second message would that your root page is probably doing some heavy lifting
Bjarn
Bjarn11mo ago
It was async, but didn't do anything. Obviously an issue, but don't think it would cause this high of a cpu time
James
James11mo ago
For comparison, my blog (all prerendered) ranges from taken 1ms-14ms. The app directory demo which has SSR ranges from 2ms to 120ms, depending on the route
Bjarn
Bjarn11mo ago
Yep that's what I experience too with the app
James
James11mo ago
So you have to have been doing something on the root page that was taking years There is no chance in a million years that the routing we do would take that long
Bjarn
Bjarn11mo ago
I'm fine sharing it tbh - https://gist.github.com/bjarn/9d54047240b005af1cf7b07cd9cb1468 Really that was it, I'm just as surprised haha the page itself didn't have functions either, but was async maybe that really is the issue I'm going to see and build again
James
James11mo ago
That's crazy also that's the layout not the actual page, i meant it was something on the page that was taking years not the layout, since the layout will apply to all the other routes that work fine
Bjarn
Bjarn11mo ago
Yup, same for the page, doesn't do anything special https://gist.github.com/bjarn/565c926daabed9ef2d10a57082f03d82
James
James11mo ago
How bizarre
Bjarn
Bjarn11mo ago
yuuup
Bjarn
Bjarn11mo ago
Well, it's a nextjs thing for sure.
Bjarn
Bjarn11mo ago
nothing to do with next-on-pages or CF Insane.
James
James11mo ago
😔
Bjarn
Bjarn11mo ago
I can feel the homepage being slow when navigating too while other pages are instant wow. I found it You're not going to believe me
Bjarn
Bjarn11mo ago
Bjarn
Bjarn11mo ago
It's... an SVG (which is a component precompiled by svgr) On the website, you see that giant world map with all the dots? That's the one. That caused all the issues.
James
James11mo ago
Oh wow lmao, how unfortunate...
Bjarn
Bjarn11mo ago
It contains too many layers, badly optimised never thought it could be the culprit. I guess nextjs was rendering it on the worker, causing these issues What a relieve haha, thanks btw to the both of you for helping out!
James
James11mo ago
Glad to hear all is well now 🙂
Bjarn
Bjarn11mo ago
Much better 🙂
James
James11mo ago
😍