Dynamic load server component list
Unanswered
Mountain Bluebird posted this in #help-forum
Mountain BluebirdOP
Hello everyone im trying to make this work for my web https://www.reactemailtemplate.com/ and its driving me crazy. Ive setup each piece snippet of code component to be a server component that performs a directory look up to get the markup and render the email, but transitions and loading are extremely slow. The EmailWrapper is the server component. Why when i do a transition (from https://www.reactemailtemplate.com/components to https://www.reactemailtemplate.com/components/buttons for eg) it doesn't stream each card one by one and instead it takes a long time to start rendering? Keep in mind i also set up loading.tsx for this page.
193 Replies
Fire ant
Nextjs js loading ui starts broken on 13.3.X, last time after i upgrade to 13.4.X the stream UI is not same like my old version on 13.3.X, i posted the questions here but none of them were aware of it.
Normaly using loading.tsx and Suspense, already can save up your work, like in the nextjs docs tutorial, but now everything is broken.
Normaly using loading.tsx and Suspense, already can save up your work, like in the nextjs docs tutorial, but now everything is broken.
Mountain BluebirdOP
this are the versions im using:
"next": "^14.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"next": "^14.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
as per my understanding it should stream each card like the documentation says: https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming#streaming-with-suspense
Streaming allows you to break down the page's HTML into smaller chunks and progressively send those chunks from the server to the client.
i also saw theres is an unstableSuspenseList but not able to use it because it breaks everything
Streaming allows you to break down the page's HTML into smaller chunks and progressively send those chunks from the server to the client.
i also saw theres is an unstableSuspenseList but not able to use it because it breaks everything
Mountain BluebirdOP
this is what getComponentData do
@Ray could you show some code on `EmailWrapper`?
Mountain BluebirdOP
sorry posted screenshots below
Mountain BluebirdOP
i also built the pages ahead with generateStaticParams but as you see transitions are slow (from https://www.reactemailtemplate.com/components to https://www.reactemailtemplate.com/components/buttons for eg)
not sure why the response from your site is not streaming
Mountain BluebirdOP
im using vercel too
yes i want to achieve the same as you shared
@Mountain Bluebird yes i want to achieve the same as you shared
try this maybe
const [{ markup, rawCode }, user] = await Promise.all([getComponentData(filename, sectionFolder), currentUser()])Mountain BluebirdOP
if dont set up the loading.tsx it takes a lot of time to do the transition
ok will try in a sec
let see just pushed the code
@Mountain Bluebird let see just pushed the code
can you show a screenshot of the folder structure?
Mountain BluebirdOP
sure
just deployed but it seems to be the same
if its streaming shouldnt i get immediate transition ?
i mean i could delete the loading.tsx right ?
@Mountain Bluebird i mean i could delete the loading.tsx right ?
I just tested with loading.tsx and I still get streaming response
Mountain BluebirdOP
check this one for example https://www.reactemailtemplate.com/components/examples it takes ages
@Mountain Bluebird check this one for example https://www.reactemailtemplate.com/components/examples it takes ages
have you test the site on local?
or does it work with
npm run dev?Mountain BluebirdOP
yes i made a local build and its a bit afaster check: https://fd48-186-12-229-158.ngrok-free.app
i mean much faster with a local build
@Mountain Bluebird i mean much faster with a local build
do you have middleware?
Mountain BluebirdOP
the one that clerk request
@Mountain Bluebird the one that clerk request
could you try rename it to _middleware.ts and test again?
Mountain BluebirdOP
@Mountain Bluebird Click to see attachment
ah could you try without it?
Mountain BluebirdOP
you mean disable middleware
yep
Mountain BluebirdOP
one min
new version with middleware renamed as _middleware.ts https://www.reactemailtemplate.com/components/examples
still the same
👀
ok let me try read file
Mountain BluebirdOP
if i wrapped every EmailWrapper into a Suspense
the transition should be instant
right ?
thats when i know Streaming its working just fine
@Ray https://streaming-phi-hazel.vercel.app/section
yes this is what i do here
import { Suspense } from "react";
export const dynamic = "force-dynamic";
export function generateStaticParams() {
return Array.from({ length: 8 }).map((_, i) => ({ name: String(i + 1) }));
}
export default async function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
{Array.from({ length: 8 }).map((_, i) => (
<Suspense key={i} fallback={<div>loading...</div>}>
<Child />
</Suspense>
))}
</main>
);
}
async function Child() {
await new Promise((resolve) => setTimeout(resolve, 5000 * Math.random()));
return <div>child</div>;
}Mountain BluebirdOP
should i set up the force-dynamic ?
I think your page is dynamic already?
Mountain BluebirdOP
but i dont have that line
do you want the page dynamic or static generated?
Mountain BluebirdOP
static at build time the only thing it can change is the user subscription status
but in your example you have both generateStaticParams and force-dynamic
if static, the content of
EmailWrapper should render when page load@Mountain Bluebird but in your example you have both generateStaticParams and force-dynamic
yes because without it, my page is being static generated
and it load instantly
create a page and try my code and see if you can get streaming response
Mountain BluebirdOP
thanks will try
yes it works
Mountain BluebirdOP
yes
with middleware?
@Mountain Bluebird yes
can you try this real quick?
const [_, user] = await Promise.all([new Promise(resolve => setTimeout(resolve, 5000), currentUser()])Mountain BluebirdOP
yest
i added it back
you mean on EmailWrapper comp ?
just return a empty div first
Mountain BluebirdOP
and pass empty string to the iframe
that work too
Mountain BluebirdOP
its easier to identify when i delete the loading.tsx wait a sec
@Mountain Bluebird its easier to identify when i delete the loading.tsx wait a sec
can you call
currentUser() in the streaming-test page and see if it still works?Mountain BluebirdOP
wait
check again
thats https://fa96-186-12-229-158.ngrok-free.app/components/examples coming all at once back right ?
yea not work
Mountain BluebirdOP
yes
on it
holy
i think thats the issue
lol
Mountain BluebirdOP
now all of the children are in loading
clerk break it
Mountain BluebirdOP
yep
maybe i can use their client side hook
and call it a day
haha
do you use it with
cache from react?Mountain BluebirdOP
no
you wanna try?
const cachedCurrentUser = cache(currentUser)Mountain BluebirdOP
never use that one
just like that ?
yes
import { cache } from 'react'Mountain BluebirdOP
async function Child() {
const [_, user] = await Promise.all([
new Promise((resolve) => setTimeout(resolve, 5000)),
currentUser(),
])
const cachedCurrentUser = cache(currentUser)
console.log(cachedCurrentUser)
return <div>child</div>
}
delete the first one ?
const [_, user] = await Promise.all([
new Promise((resolve) => setTimeout(resolve, 5000)),
currentUser(),
])
const cachedCurrentUser = cache(currentUser)
console.log(cachedCurrentUser)
return <div>child</div>
}
delete the first one ?
const cachedCurrentUser = cache(currentUser)
async function Child() {
const [_, user] = await Promise.all([
new Promise((resolve) => setTimeout(resolve, 5000)),
cachedCurrentUser(),
])
return <div>child</div>
}like this
Mountain BluebirdOP
its the same
@Mountain Bluebird its the same
ok go create an issue on clerk 

Mountain BluebirdOP
haha
yes i should do that
https://www.reactemailtemplate.com/components what do you think now ?
between the click and the transition there is still a delay should i add back the loading.tsx for that instant feel ?
Mountain BluebirdOP
for eg https://www.reactemailtemplate.com/components/examples this one still feels slow
the transition
but i guess streaming is working rn
yes it slow but at least it is streaming
Mountain BluebirdOP
is there an easy way to check is working on network tab or something ?
blue line is from streaming
look like its not working?
Mountain BluebirdOP
https://www.reactemailtemplate.com/streaming-test well here its working
i just dont get why i get that delay in transition
(the middlware is active so that doesnt interfere with streaming)
Mountain BluebirdOP
i mean the delay between the /components page to any section
its too long maybe im doing something wrong
Mountain BluebirdOP
Masai Lion
Mountain BluebirdOP
to render i mean
yes i was checking if the issue was with the EmailComponent so i replaced the <Child /> for that one
but thas not the problem
Mountain BluebirdOP
@Ray look when i try to get to /components/example
got timed out
got timed out
Mountain BluebirdOP
😢
will get another look tonight
@Ray ts
const cachedCurrentUser = cache(currentUser)
async function Child() {
const [_, user] = await Promise.all([
new Promise((resolve) => setTimeout(resolve, 5000)),
cachedCurrentUser(),
])
return <div>child</div>
}
like this
Mountain BluebirdOP
we thought that the clerk function was breaking it but we missed the random on the setTimeout, so thats not the problem
Mountain BluebirdOP
what im noticing that the local build is super fast and it does streaming
maybe i have a deployment issue
Mountain BluebirdOP
yes the local
npm run build is super fasti dont know why
@Mountain Bluebird i dont know why
might be the dynamic import
Mountain BluebirdOP
that one right ?
i use the approach of the cache you mention
its a bit better but still slow
try this
const Email = dynamic(() => import(""))Mountain BluebirdOP
const Email = (
await import(
).default
modify that one ?
await import(
../components/emails/${sectionFolder}/${componentName})).default
modify that one ?
yes
or try import it directly and see if it still slow on vercel
Mountain BluebirdOP
😢
blank
i think the markup read is fast
but does it stream?
Mountain BluebirdOP
the issue is with the render
yes the streaming is working
oh
Mountain BluebirdOP
its even working on production rn
https://www.reactemailtemplate.com/components if you check any of those, the thing is the streaming is working BUT why the navigation are not immediate ?
const markup = new Promise(resolve => resolve(<Email />, { pretty: true })try this? lol
Mountain BluebirdOP
yes now because it has the loading.tsx you feel it instant
for now i will leave it as is max 5 component per section
if you put a lot of components in a section is painfully slow
it took about 3s before the streaming start
Mountain BluebirdOP
yes
pretty annoying at least for me
😆
let me test a bit
yes the problem is the render function
Mountain BluebirdOP
on your is instant without loading.tsx ?
oh you still have it but its much faster
it does have loading.tsx
Mountain BluebirdOP
yes i notice
@Mountain Bluebird yes i notice
const markup = await new Promise((resolve) =>
resolve(render(<Email />, { pretty: true }))
);this fixed that lol
it blocking the process without it
Mountain BluebirdOP
test it local and it seems to be working
will push it
and let see on vercel env
should work
its live
still slow
lol
Mountain BluebirdOP
yes
https://www.reactemailtemplate.com/components/features-examples this one its like 5 sec
well the streaming its working
but the transition is slow
is your project on github?
Mountain BluebirdOP
yes it is
dont worry, will leave it as is for now