bruh you haven't even finished watching the video yet
@koteelok201415 сағат бұрын
I can't believe it, but I actually understood the code from 0:50 without explanation from the video. Needed to sneak a peek at core-js's implementation of setImmediate tho. My basic understanding was: prerender is a function that can take some time to run or might not, so using setImmediate we can stop "rendering" and get intermediate result from synchronous part of rendering process.
@denissorn11 сағат бұрын
17:28 'And I can even delete this suspense.' It seems that from this point, all SlowComponents are delayed by 5 seconds.
@baka_baca21 сағат бұрын
This is beautifully simple and brilliant! I love elegant solutions that rely on basic language features over magical logic.
@Dorlonf9 сағат бұрын
Oh I was so confused with `params` throwing errors they should be awaited. The explanation is great, thanks Theo!
@nasko23567913 сағат бұрын
Was literally playing with suspense / loading / dynamicIO yesterday, it's like you're reading my mind. Great stuff!
@wyndmillКүн бұрын
this is a really good video, thanks for explaining that code well
@bloodonthesnow6 сағат бұрын
thank you Theo this is the best Next.js video i've seen all year
@henilshah336818 сағат бұрын
10:45 Question about the TopNav (which has the "use client"). I follow when you say that's static and should be rendered ASAP, how does the client side js work out? I mean what if we are using client data (AV info, date time, etc)? Where does that fall into the event loop and stack or whatever?
@faizanahmed930420 сағат бұрын
18:25 even though if you remove dynamicIO flag, isn't it will work the same way? By separating Contents component?
@philheathslegalteam12 сағат бұрын
No they swap out the function. They use renderToStream for non dynamic io
@piaIy9 сағат бұрын
Without dynamicIO (and no PPR enabled) the pages are either completely static or dynamic. PPR in Next.js 14 enabled the combination of static and dynamic parts on the same page, and dynamicIO builds on this concept while also adding "use cache" to the mix.
@Scyth3zКүн бұрын
what do you use for these boards? Like what you pulled up at 2:10
@zldyttКүн бұрын
excalidraw
@mihirphadnis221 сағат бұрын
He is hosting exaclidraw himself, If you want there is excalidraw plugin in obsidian or logseq to use offline
@TheIpicon3 сағат бұрын
swear to go I understood it immediately. give me a job Theo .\/.
@ovflowdКүн бұрын
The moment I saw those setImmediate and controller abort, I assumed there was some funny prevent async loops to get kicked in shenanigans. This is such a clever way of using JavaScript's (or in this case, Node.js's Event Loop)
@vanilla_masterКүн бұрын
seeing destructuring of new promise into prelude and postponed without awaiting it leave so many questions
@UCzIiTeduaanyEboRfwJJznA22 сағат бұрын
Enticed by the prelude, but explanation remains postponed.
@patolorde17 сағат бұрын
Classic Excalidraw Theo!! YES
@ndykman_pdxКүн бұрын
So, simple question. Why do you just do a static HTML page with all the placeholders and state by default and then bring in dynamic content in every case? In essence, force the developers to make as much of the site static as possible. Take the pokemon page. Make it static with the default greyed out pokemon choices that boom, get replaced with non-greyed out new choices when they are ready (or when the pick new random button is chosen). Also, why do components not require static placeholder content? I am thinking back to the old days of UI builders, when you brought in a component, it'd be run "in design time" and the content was often just a placeholder that you could still see how to fit into the app, but with faked or blank data. In that case, just have the framework be able to spit out a static rendered site to preview the design as well as the placeholder static HTML until all the scripts run and actual content is ready with just a flag? Or are developers so obsessed with not repeating themselves that making a bit of mocked up HTML to give an idea as what is to come as well as the real thing is just too much to handle? ETA: I don't think the above model is inconsistent with server side rendering in general. After all, nothing says that if you have a page with some components, you have then have to construct all the HTML on the client. The components may happily serve back the HTML to be placed inside the page, I would imagine.
@azzamalotaiby22 сағат бұрын
womp womp
@balkibartokomous2 сағат бұрын
Yes this. The video doesn't quite explain why anyone would allow a slow component that takes more than 2 seconds to block everything server side and not just turn that into a client side component that fetches data from the client. Maybe there is a reason but this didn't explain why this problem exists to begin with.
@dead-claudia22 сағат бұрын
0:54 i got a question tho: why is the controller abort not wrapped in a try block? it can throw if any of its abort listeners throw. and yes i understand most of it. helps that i've been in varying degrees in the framework business for almost a decade now tho. and that setImmediate trick iirc won't work the same in browsers bc they don't drain the promise queue fully between timer tasks.
@MrDapxitlo15 сағат бұрын
>and that setImmediate trick iirc won't work the same in browsers bc they don't drain the promise queue fully between timer tasks. the prerendering happens on the node.js not browser
@paw56513 сағат бұрын
This video shows how much we need next.js dev tools.
@MissTitanK335 минут бұрын
So, i paused it where you showed it. This is what I found. This code shows how to manage server-side rendering with React using prerender and an AbortController. The prerender function renders a React component () on the server, and the AbortController allows you to cancel the rendering if it takes too long. A promise is used to handle the process, ensuring the result is either successfully completed or an error is caught if something goes wrong. Two setImmediate calls are used to control the flow. The first tries to render the component and handles any errors. The second cancels the render using the AbortController and resolves the promise with the result, even if the process was stopped early. This setup ensures rendering doesn't hang and that server resources are used efficiently. It's helpful for managing timeouts and handling errors in server-side rendering. Lets see how close I am.
@Zitr000ne17 сағат бұрын
Correct me if I'm wrong, could you not use export const dynamic = 'force-dynamic' to prevent caching? That's much more obvious that randomly calling headers().
@MaxPicAxeКүн бұрын
Function color is a terrible indicator of this. It indicates long-running work, sure, but not necessarily "non-static server-side work" as required. It does not indicate whether a function is deterministic. A function is deterministic if all its dependencies are deterministic. It's that simple, there's no alternative. Either the dependency graph must be tracked at the language level, or an explicit label must be set by the developer. But forcing developers to use function color as an indicator is going to result in terribly written code. Please do not push this, and instead reconsider your perspective! I don't suggest conflating two clearly distinct concepts because of surface-level convenience.
@greyshopleskin2315Күн бұрын
I’m a bit of a hater of the JS world but I think this way of doing things makes perfect sense. You say async functions indicates long running work. No, they indicate asynchronous work. Why do you use async for? For I/O. What is a property of I/O? It’s indeterministic. Ok, so we can assume async functions are not deterministic. What about not async ones? Well, those will be deterministic most of the time. How can you have a function that does no I/O but is not deterministic? By doing stuff like reading global variables and so on. Which seems to be uncommon in JS. So most of the time they will be deterministic. If you allow to use a directive like “use dynamic” in non async functions in case you are doing weird stuff, it should be fine. This combination of async and sync functions with “use dynamic” allows to determine whether *user* code is dynamic or not. For dependencies, it’s enough most of the time but not always. If you use a dependency that renders dynamic content, it’s gonna be async most of the time, forcing your function to be async. But some dependency could render dynamic content using sync functions.
@greyshopleskin2315Күн бұрын
To be fair I see a lot of potential problems with this, but most of the time it will work fine. There’s some edge cases that can bite you tho. Anyways that’s frameworks for you anyway. If you want convenient magic it will eventually hurt you. If you want control over your code base and behavior of your project, and don’t want surprises, you’re better off using no framework. I don’t think what we saw in the video can be implemented without any gotchas. If they put this behind a feature flag is fine.
@aravindprabhakaran386819 сағат бұрын
I think use cache basically allow for the opt in to be “sync”. But yes there will be some requests that get a reduced response. if the App accesses headers at all doesn’t it just opt out of any pre-rendering. Which I guess was the previous behaviour. But then you can’t use a specific header as a cache key you end up making the whole thing dynamic - I am thinking maybe adapting the shell depending on the role in the users claims. The solution there might be to see if you can add an async function before every request on your edge and sending the next app your variables you want to cache on. That’s a bit custom tho and no idea if that’s possible.
@TheYinyangman13 сағат бұрын
The headers was fine it just means there is a request header so it’s dynamic as it’s based on a user interaction. No request header no user interaction. If you need a request header and it to be cached use a dynamic function and add the cache header yourself
@aravindprabhakaran386813 сағат бұрын
@@TheYinyangman ahh yes I think I misunderstood. In next, is this pre-rendering code part of the build step so the outputted html is then set to a CDN for actual request time ? I kind of thought of it still producing a serverless function (that can be deployed to the edge) and the function has html ready rather than React style rendering i.e. it is pre-rendered.
@samuelgunter23 сағат бұрын
before watching this, I'm guessing it has something to do with detecting async code or doing some kind of partial render until the first async or suspense thing
@samuelgunter23 сағат бұрын
pretty much spot on. train of thought included JS event loop, what AbortControllers are for, what prerendering is, and the concept of partial prerendering came to mind let me know if there are any jobs I can get while still in school (done with everything except for required CS upper divisions, since I came in with so many AP and dual credit courses)
@Luisllaboj1917 сағат бұрын
So the new Promise() executor function runs synchronously and when it calls setImmediate() it schedules a callback on the tasks queue to be executed as soon as the call stack is empty, the first callback starts the pre-rendering (does this happen in the background, in a microtask?? Not sure) and the second callback terminates the pre-rendering by aborting the controller which signals the pre-render to stop there, then it resolves the promise with the current result (only the static parts) and since both callbacks closed over the same result variable both have access to its latest value which is the static parts of the App pre-rendered.
@codlp780Күн бұрын
very nice explanation, love those advanced video
@virtual5754Күн бұрын
Alright, I understood that async makes dynamic component while not async makes static. But then how should completely static pages load their initial data from database and remote servers? This requires async keyword to be able to use awaits (because promises are not cool), which automatically makes it dynamic.
@LiooRyuuguu21 сағат бұрын
can‘t you use the „use cache“ flag so it gets cached and therefore becomes static on second render?
@vildivent17 сағат бұрын
If you load data from database to your page, page is no longer considered as static. Static is if you hardcoded all data once and they don't change ever.
@virtual575414 сағат бұрын
@@LiooRyuuguu that sounds like isr without getStaticProps, but for a page that might not even have it (no dynamic segment). Isnt there proper way to build static pages like before, at build time?
@virtual575414 сағат бұрын
@@vildivent you missed some advancements of past several years. There is thing called isr that allows to make static pages, but rebuild them at runtime when needed
@piaIy11 сағат бұрын
Next.js statically prerenders every component during build by default unless they're explicitly opted-out, either by being wrapped in Suspense or using any Dynamic APIs like searchParams (and there's also the route segment config, but that's being deprecated in favor of dynamicIO). And I think you're misunderstanding ISR, it's just the ability to update a _prerendered_ page, and this prerendering happens initially during build.
@musagillani5399Күн бұрын
idk if im wrong but didn't they just go the other way around to indentify cacheable content? i.e before you _explicitly marked content as dynamic_ using functions like headers(), now you need to _explicitly mark content as static-ish_ using "use cache". Might be a stretch but cool way to think about the model tho i guess
@KevinOsterkilde3 сағат бұрын
2:05 you just love putting yourself on a pedestal, even if not at the top 😂
@RemotHuman22 сағат бұрын
Ok so my understanding is we assume that async = dynamic and not-async = static. Then you can opt out of async being treated as dynamic by adding “use cache”. So we just need a way to opt out of not-sync being static. Not async is probably static almost every time, I can’t currently think of a time where it wouldn’t be (but maybe I’m not thinking of something), but it doesn’t literally have to be. For example you could put a math.random thing in there and make a decision based on that, now it’s dynamic. Or I know you can actually read from SQLite without async eg in drizzle, you could also read from a generic in memory store (ie just a js variable) that changes over time. I don’t think that applies here though because I assume it’s only meant to be being rendered serverlessly, where the state of the program is reset after every function call
@piaIy12 сағат бұрын
Components can be forced to be rendered dynamically by calling `await connection()`, which replaces unstable_noStore and "force-dynamic". And there's a catch, async components will become static if every async call inside is cached. Theo should've mentioned this because he ran into this problem in one of his videos called "I built the same app with 5 different stacks". He fetched an array and shuffled it randomly, but since the result of the fetch was cached, the function returned the same result until it was forced to be dynamic.
@jorgedavidfernandez97246 сағат бұрын
Videos like these make all the clickbait stuff tolerable 😅. Thank you!
@yubtubtimeКүн бұрын
This is dope and feels so obvious once you see it
@iamfrankstallone15 сағат бұрын
setImmediate is noted as deprecated on the MDN docs. Does this not matter because Node says it’s supporting it?
@t3dotgg15 сағат бұрын
Correct. Less useful feature in the browser
@arduanoКүн бұрын
What about when I have a CMS I want to fetch things from, but still want the results to be cached? Your idea only works for webapps, not static sites. I don't think it's a good idea to implicitly put all the "dynamic" CMS-defined content to end up behind a dynamic suspense.
@DhananjayNaikКүн бұрын
Wow. Just wow!
@KopoLPedov22 сағат бұрын
22:14 - you are wrong, it is not "javascript itself". setImmediate and even the event loop doesn't present in js specification.
@faraonchСағат бұрын
Very well explained! 👏
@meka49964 сағат бұрын
Amazing. I started to like React this year!
@hank9th20 сағат бұрын
Commenting my guess as to what this code does before I find out how wrong I am: It hijacks however promises work in JS to ensure the root is rendered before anything else that might depend on it.
@mrsideshowjack19 сағат бұрын
This video makes me want to refactor every prod app during the holiday, please stop uploading for a few weeks pls thx
@zwanz0r13 сағат бұрын
"it uses plain JavaScript to know what's cashed or not". I understand that it improved somewhat, but there is still compiler magic in `"use cache"`. A wrapper function would be better IMO.
@mj-meyer16 сағат бұрын
I missed these excalidraw videos! MOOOOOOOOORE please!
@dimitrigilbert13 сағат бұрын
When trying to understand the code at the begining, this poped into my mind (I didn't have the async part though ^^) and I was like.... "Hum.... naaaah, must've missed something, this seems....it would give me feelings". It does... 'tis both smart and feels incredibly "shaky" to me, I have so many questions... All JS engines works that way ? What if for some reason big brain me wants to use callbacks ? This seems like a dangerous toy to bring to school ! isn't it ? Moar questions, maybe...
@cherubin7th9 сағат бұрын
I only use JS to draw some boxes. Not because I want to but because browsers force me to. (Actually TS).
@vitosnatios21 сағат бұрын
hard not to love nextjs
@matti59212 сағат бұрын
Could you give some short introduction, in the beginning, what this video is actually about, please.
@JohanStrandOne14 сағат бұрын
oh! So you throw two things on the event loop and let the second be a canary for if the first is async.. that should do the trick! got ten minutes on before it clicked though.
@lsumail218918 сағат бұрын
A promise can be destructiveed?
@balkibartokomous23 сағат бұрын
Couldn't this be solved by making sure anything that is dynamically loaded as 'use client' and make sure the rest of the page could be statically rendered? That's how i've been understanding use client so it will be a surprise to me, if it doesn't work this way.
@t3dotgg23 сағат бұрын
You don't understand "use client". Files marked "use client" still run on the server.
@balkibartokomous23 сағат бұрын
@t3dotgg but to solve the problem that you presented in the video where waiting for the slow components was preventing the entire page from rendering wouldn't that have been solved by putting those in components with use client?
@t3dotgg23 сағат бұрын
Depends on how you fetch the data. If you move the data fetch to an endpoint and the component gets the data via react-query or useEffect, then yes, it's not blocking - only because you wrote it in a non-blocking way. If you fetch the data in the server component and pass it to the client component, the "use client" does not change the static/dynamic nature of the request.
@balkibartokomous22 сағат бұрын
@t3dotgg i see now, thank you. To nextjs credit they did encourage using server actions to get data from client components so as long you did that it likely prevented this issue
@t3dotgg22 сағат бұрын
@ they never encouraged servers actions for data fetching. Common misconception I’ve tried really hard to clear up.
@itslonewolf7427 сағат бұрын
We just had something similar to Suspense in Inertia 2.0
@erithax12 сағат бұрын
Overloading async await to also carry staticism/determinism, in addition to asynchrony, feels like a mistake. The elegance of implementation should be a much lower priority than providing users sound abstractions that enable them to solve all aspects of a complicated problem. Glossing over it with async is not the right solution, in my opinion. Enjoyed the video, though.
@zwanz0r14 сағат бұрын
DynamicIO should be called DynamicAsync. It's not about IO, it's about Async.
@LutherDePapier12 сағат бұрын
"Election meltdown watch party." 😂😂😂
@linuxguy119922 сағат бұрын
As a C developer I can confidently say I have no fracking idea what a promise is, also what's a try-catch statement? Anyways, still love watching these videos and the technology behind web dev, even though I will probably never touch Next.js in my life.
@wil-fri21 сағат бұрын
Look about an event loop. The code is gonna wait for that to happen to then run the thenable or the next line. Or throw an exception
@kassios18 сағат бұрын
Why do that to yourself my friend? Why share our frontend pain and tribulations…
@linuxguy119918 сағат бұрын
@@wil-fri What's an event?
@linuxguy119918 сағат бұрын
@@kassios It's some sort of morbid curiosity or something, but hey at least you guys don't have to ever have to deal with self modifying code, bit-banging custom quad-state serial interfaces, or eye diagrams!
@kassios17 сағат бұрын
@@linuxguy1199 that's why we rely on you guys to actually make things move, while we safely play ontop of a compiler to create the most complicated button to present to management. 😃
@mhRealishСағат бұрын
But.. SetImmediate is deprecated right?
@aymenbachiri-yh2hd17 сағат бұрын
thanks for the video
@philips806518 сағат бұрын
Every time I learn a new rendering paradigms especially from vercel, I always wish people create videos not just about the web vitals comparison but also the edge requests utilizations for various rendering structures of a website. For small scale indie devs, it gives a lot of breathing space before shelling out money for pricey tiers.
@Dik131WZD19 сағат бұрын
So, does it mean that we don't need Astro anymore?
@victoreleanya43758 сағат бұрын
Thanks for sharing
@harishkarumuthil576112 сағат бұрын
thank you!
@GottZСағат бұрын
2024.. I'm getting freakin old I guess.. (36 now) more than a decade ago I've already specially tailored slow components to asyncronously inject state into context.. using a custom self-made implementation of promises (essentially a proper callback wrapper), before we had promises.. in IE 5.. so.. having figured what this code does, (literally exploiting a reproducible race condition), as I know event loop control pretty damn well.. where is that job you were talking about? I legit went into sys administration and backend dev because I got sick and tired of bad leadership in full-stack environments..
@calholli22 сағат бұрын
So we still have to wait for the slowest thing to load anyway... cool
@vildivent17 сағат бұрын
The message is that we don't have to block entire page cos of one slow component. And if there's no waiting in layout we can store it in cash as static data.
@calholli13 сағат бұрын
@@vildivent I get it.. lol. I'm just pointing out, it doesn't make the slowest thing any faster; so in the end, you're not actually making anything faster. I guess: unless you need to click on something that has already rendered- then you're not waiting for that 'slowest" thing and are already moving on to the next page/link, etc. But most of the time, the "static" info is just text and aesthetic stuff. IDK.. It's not much of a change. Getting everyone fast computers and fiber internet is what really makes things faster. These little incremental/remedial tweaks are... nominal.. marginal... superficial; it's not really doing anything- just the appearance of doing something... cosmetic.. aesthetic. The page still can't really function until it loads. lol.. Just because you "see" a few things earlier, doesn't really help anything. IDK.. I'm just being a negative nancy, apparently
@inderjotsingh58686 сағат бұрын
do more videos like this 🙂
@foooosi8 сағат бұрын
I don't like magic
@ErrorINAOfficial8 сағат бұрын
🍋
@blazed-space19 сағат бұрын
JavaScript is like women. I love 😍 JavaScript with all my heart but I will never understand how or why JavaScript works. I just know it does and without it I would not be here
@mochamadrizkycahyadiputra3747Күн бұрын
nice video
@burgermancan12 сағат бұрын
delicious
@AbstruseJoker22 сағат бұрын
all these videos are obsessed with TTFB. no one cares about building anything anymore
@the_nurk23 сағат бұрын
uh, duh
@the_nurk23 сағат бұрын
good tech tho fo sho. there's more symmetries to be exploited for compiler efficiency. and there are more symmetries to uncover that expand the capabilities of compilers.
@zigaio14 сағат бұрын
2000 IQ
@leanghok120Күн бұрын
2 views in 1 min, bro fell off
@popdastackbruh2515Күн бұрын
Xqc ahh comment
@calholli13 сағат бұрын
Press refresh.. It doesn't load life data.
@shawqicausesКүн бұрын
First comment, YAY!
@AryanKumar-d9d8jКүн бұрын
first
@i.reutenkoКүн бұрын
Meh, I was asked about a similar piece of code back in 2020 during one of my interviews. Of course, it had a much easier use case, but nevertheless