In short
Software Engineering Daily Podcast Episode Summary
Episode Title
Next.js 15 with Jimmy Lai and Tim Neutkens
Episode Description This episode discusses Next.js, an open-source JavaScript framework developed by Vercel, built on top of React. It aims to streamline web application development through server-side rendering and static site generation. The episode features insights from Jimmy Lai and Tim Neutkens on the latest updates in Next.js 15, released in October 2024, highlighting significant new features and improvements.
---
Key Participants
- Jimmy Lai: Software Engineering Manager at Next.js.
- Tim Neutkens: Tech Lead for Next.js and TurboPack.
- Kevin Ball (KBall): Host and VP of Engineering at Mento.
---
Key Topics Discussed
- Introduction to Next.js and the Latest Release
- Next.js Overview: An open-source framework for web application development.
- Version 15 Release: Highlighted significant upgrades, including:
- Enhanced TurboPack integration.
- Support for React 19.
- New Features in Next.js 15
- Release Timeline: A longer polish period led to the October release.
- Performance Improvements:
- Stability and performance enhancements.
- Introduction of new components such as the Nexus form component.
- TurboPack Development: Stable for development, focusing on improving the speed of development iterations.
- TurboPack
- Purpose: A new bundler and compiler tailored to replace Webpack, designed to handle the increasing complexity of modern web applications.
- Performance Metrics: Promises a significant speed increase (95% faster hot module reloading).
- Caching Mechanism: Introduced disk caching for persisting build work to improve efficiency.
- Async Request APIs
- Changes: Transition to using promises for headers and cookies, aiming for better clarity on dynamic versus static requests.
- Dynamic I/O: Aims to simplify developers' experience by allowing Next.js to determine when content is dynamic based on async usage within user code.
- Enhanced Stability and Error Handling
- Collaboration with the React team to improve hydration errors, making debugging easier for developers.
- Relationship Between Next.js and React
- Clarification of misconceptions regarding ownership of features like `useClient` and `useServer`.
- Next.js seeks to enhance React’s capabilities, while React provides foundational support for Next.js features.
- OpenNext Initiative
- Discussion on improving documentation and deployment practices for self-hosted Next.js applications, ensuring ease of use across various platforms.
- Goals:
- To simplify the deployment process on serverless platforms.
- Create community-maintained resources for deploying Next.js applications.
---
Key Takeaways
- Stable TurboPack: Offers significant performance boosts for development cycles.
- Async APIs: Now simplifying dynamic content handling through a promise-based structure.
- Next.js and React Interconnection: Next.js is deeply integrated with React's development, enhancing both frameworks.
- OpenNext: Aims to broaden the deployment capabilities and documentation for Next.js, allowing flexible hosting solutions.
- Community Focus: Engagement with the community and continuous improvement of Next.js through shared insights and feedback.
---
Conclusion The episode provides detailed insights into Next.js 15, emphasizing performance enhancements, new features, and the relationship between Next.js and React. It highlights a community-driven approach to evolving the framework while maintaining stability and developer experience. The discussion on TurboPack and async APIs reflects a forward-looking vision for Next.js as it adapts to modern web development demands.
Written by AI. May contain mistakes. Listen to the episode to check what was said.
Transcript
Automatic transcript. May contain errors.0:00Next.js is an open source JavaScript framework developed by Vercell. It's built on top of React and is designed to streamline web application development using server-side rendering and static site generation. The framework's handling of both front-end and back-end tasks, along with features like API routes and file-based routing, have made it an increasingly popular choice in the web dev community. Next.js 15 just released in October of 2024 and introduces significant upgrades, including enhanced integration of TurboPack and support for React 19. Jimmy Lai is a software engineering manager at Next.js, and Tim Newkins is the tech lead for Next.js and TurboPack.
0:37They join the show to talk about Next.js and what's new in version 15. Kevin Ball, or KBall, is the Vice President of Engineering at Mento and an independent coach for engineers and engineering leaders. He co-founded and served as CTO for two companies, founded the San Diego JavaScript Meetup, and organizes the AI in Action discussion group through Latent Space. Check out the show notes to follow KBall on Twitter or LinkedIn, or visit his website, kball.llc.
1:17hey guys welcome to the show hey thanks for having us yeah good to see you so let's start out a little bit with some quick introductions so let's actually i'll throw to you first jimmy jimmy do you want to introduce yourself and your background and how you got involved with next yeah so my name is jimmy i'm a french software engineer before vercel i used to work at meta in London. I used to work on React Native and on some internal products. I used to work a lot on web performance and anything related to that, like to product infrastructure in general. I decided to join Vercel because I wanted to work with a company that focused on, well, actually on performance on the web.
1:58The mission, Guillermo's mission really struck me there in terms of bringing the amazing technologies we had at Thanks to our companies. I didn't start working on Next when I joined. I used to work on the FeatureFlex, but I quickly joined the team back in, what was it, end of like 2022. And ever since I've been working mostly on the AppRatter a year ago, I started managing the team. and we've handled mostly the 15 release and a lot of the great work team has completed in the version 14.1, 14.2. Yeah, that's it on me. Awesome. How about you, Tim? Hey, I'm Tim. I've been working on Nextless for a while, since like 2016 when it first came out as a contributor and eventually joined for Cell in 2017.
2:51And since then I've been building quite a lot of different things, but mostly working on NextShets across all of them and building out the team. And now I'm tech lead for NextShets and TurboPack. Mostly focused on TurboPack nowadays and trying to get that over the line and into the hands of everyone. Yeah. So the impetus for this is y 'all just had a big release. Do you want to tell us kind of what that was and what's in the box? Yeah. So this release has been a long time coming, actually. For those not familiar with the release schedule, we used to drop really regularly in the past year. After we shipped AppRatter with Next13, we were really following up on it every month or so.
3:36With Next15, we decided to take a slightly different approach. We wanted to take a bit more time to make sure it's really polished. And so we released a release candidate back in May. and took us quite some time to ship it because we're now basically in October. It's been six months. We really took the opportunity to bundle as much really nice changes as possible so that we could set it as the new baseline for the app router. We added an insane amount of stability improvements and performance improvements. We sprinkled some features like the Nexus form component or the after hooks, which allows you to tap into the request lifecycle.
4:18And we also, you know, improved so much on the TurboPack development story, which to me, I think is actually maybe the biggest headline for Next15. TurboPack is now stable for development. Maybe Tim can say more about it as well. Yeah, there's definitely been like other changes as well. Next to features, there's been a lot of work on like polishing, things that people run into every day. So it's definitely been a strong shift in focus towards stability improvement. So just making your day-to-day better, in short. So if you ever use Next.js or any React framework that does service rendering, you've seen these hydration errors because you add a date somewhere and the date changes once it gets to the browser, that kind of thing.
5:04Those errors, we just saw that everyone was struggling with them. We were struggling with them ourselves as well inside of Purcell. it was just like not clear where and what it was causing it right so like what code and like what was even changing on the page that caused the error so what we did is we work with the react team to make react better in that regard so like that react can actually show like this is a diff basically for like where this thing is mismatching and that is the component that was causing it so what's really nice now is that you get all these like small tweaks that may seem like very small stuff but in the end like it's affecting a million developers every day because it just makes it easier to solve like your iteration errors or like some other errors that didn't have correct source mapping or things like that so that's like just on the nexus 15 side of things and then as part of nexus 15 we're also shipping turbo pack for development so turbo pack is like the new underlying compiler and bundler for nextjs then we're planning to make it more like a generic bundler in the future but right now we're just focusing it on nextjs because that's like the largest service area and like once that like works well for it once it works well for nextjs and it can build all like all the dependencies that we see people use every day then it will be a really good like generic solution already as well and so we're first focusing on first we focus on development because that's the thing that most people were running into had complaints about things were too slow, took too long to open a page.
6:34Or when you make a change, it would take seconds sometimes before you can see it on the screen, be it CSS changes or code changes. So basically, we set out to build a faster solution than what Nexias had up to that point. So we built this new architecture to scale to the large amount of code that we see nowadays. So when it started working on Nexias eight years ago, JavaScript apps were certainly not small and the like note modules meme has always been true a little bit. But there, I would say like the bottomless pit has gotten a lot like more bottomless in like the recent years. Where like what we basically see is that there's more consolidation of libraries and it's not bad at all, really.
7:16Like it is really nice. So you see more icon libraries, more design systems that are just like out of the box, have everything that you need, right? So previously where you would have to go and write like every single component yourself, like eight years ago, for example, you just had to write your own button component, write your own menus, write the dropdowns, everything yourself. Now you just have out-of-the-box toolkits that have everything. But with that comes them shipping a lot of components by default. And that means we have to bundle more. So that's not inherently bad. It just means that our tools now need to scale up with that demand of overall usage.
7:54and basically what that meant for us is that in practice what we would see is we would see like smaller apps get over 10 000 modules where previously that was not the case or in some like exotic cases where you accidentally import like five different icon libraries that all export like 10 000 modules you would see like 30 000 plus modules for like something that seems to be like a simple case and when i say modules i don't mean like it's the great npm inflation basically yeah there's like some like libraries that ship like icons that like have multiple icon libraries so you can pick and choose between like different icon libraries and use different icons from a design perspective maybe not the best idea but it's very convenient and that's why we see a lot and it's not a bad thing like i said like it just means that there's more code to be compiled and it doesn't mean that we ship more code to the browser per se because you have stuff tree shaking and all that but from the compiler and vendor level like we first need to know about everything that exists before you can actually shake them.
8:50And that causes the compiler to take longer, even if you only use like one icon from this icon library. So that's why we set out to build like a new compiler and mandler that can scale up with these like high demands of like larger apps. And then like besides that, also our own like Fercel's internal app for like Fercel.com, for example, started growing quite a lot as well. We added hundreds of engineers at Fercel. So it was just like more people working on it day to day as well. So the code base itself is growing way more quickly than it used to. And in order to keep up with the scaling of that, we just had to create a better solution.
9:26So that turned into TurboPack. Eventually, we basically investigated all different kinds of solutions, but found that it doesn't really fit with the way that NextGest works or the way that we wanted to do Node.js and browser compilation and a bunch of other things. And in the end, we ended up building a new bundler that should set us up for the next like 10 years at least and we can still optimize further as well so like where we're at today is like this is just a start right so we're at a certain performance that's much better than a web like the previous compiler but the current performance of the new compiler is still like only like at a certain point where we still are not super like we're happy with where we're at and it's much better than where it used to be but it can still be so much better from here so that's where we're working on disk caching and some extra caching layers to make things even faster across rebuilds.
10:18So just to make sure I understand, this is replacing what you were using Webpack for and what other frameworks might use, like some combination of Vite and Rollup or something like that. Exactly, yeah. I think what we found, like James said, building on Webpack is just that we were sort of architecturally limited. I actually don't remember how old Webpack is probably, you know, around 10 years old, Tim. It's over 10 years, yeah. Yeah, and so the whole structure, the whole, like, amount of legacy had support, like, the whole host of weird options and quirks that you could configure via Webpack was limiting us, and so we sat down and we were thinking, like, what if we could start it from the ground up?
11:02Like, you know, we considered, obviously, that's going to be, you know, we considered using Vite and, like, the roll-up option as well, But I think we took a really big bet here a few years ago, right? We believe we have the solution to scale it properly. And what's exciting really now is that this is starting to pay off. We spent the last few years iterating on just the basics of making a bundle work. But the great thing to me, which I was really impressed talking with Tobias about it at the last conf, is now that we build the bundle element with the idea that you can separate each of the tasks that it does and cache them individually at the function level instead of at the module level, this allows us to avoid repeating any work that we don't need to do.
11:52First off, we can see that from the HMR performance boost, which is sort of mind-blowing. You hit command save on a file, and it just, you know, it feels like magic to me. Yeah, we find that it's 95 % faster than what it was before. So it would take, one example is like a one page on Overcell's own app. It's taken like 900 milliseconds and it went down to I feel like 45 milliseconds for the exact same change, right? So like changing some like CTSS or Gumball. So yeah, one of the problems that Wepic had is or still has like in general is that the moment you start, like you add more modules. So modules are like JavaScript files or TypeScript files or CSS or anything else that you add like loaders for, for example.
12:37The moment you have like over 10 ,000 to 30 ,000 modules, there's just an inherent overhead on processing like on module replacement updates. So like fast refresh updates. So what that means is that anytime you make a change, it doesn't matter what change it is. So if it's a JavaScript file change or a CSS file change, which you might expect the one is faster than the other, but actually it's not. So the CSS file change will still take like 900 plus milliseconds because of just the overhead of having to crawl the entire list of modules. And with TurboPack, we actually made it so that TurboPack only has to redo the work that is affected by the change.
13:14So that means if you're using, like you're writing CSS and you don't have any customization, so you don't add like post CSS or till end or anything like that, we only have to recompile that single file instead of recompiling like the entire module graph or the entire like chunks or like JavaScript files output, for example, or CSS files output. Like we don't have to recalculate those. We only have to recalculate like the part that's affected by that change, basically. well and that amount of timing change is a real difference for your dev cycle right 900 milliseconds is still like not massively long but that's i make a change i save it i go see it reflected whereas 45 is like i'm tinkering with this and it's live updating with me and i can iterate this is this right is that right it's like using dev tools essentially except you're using your code base yeah yeah and yeah exactly what i was getting on in terms of like since this is now the baseline for us it allowed us to basically really quickly well i say quickly but this is years in the making to really quickly add like a persistent caching layer on top of that so for hmr it's all in the memory we do this instantly but you still have to hit the cost of like actually starting up and computing the task and the amazing thing we showed last thursday at conf was what if we could just persist all of that work now to the disk cache what if instead of like Well, instead of saving it in your session, we could save it across forever.
14:41On all of your sessions, you stop the server, you go to sleep, you wake up the day after tomorrow, and you can pick up exactly where you left off in hundreds of milliseconds. That's a lot of time saved. That is a lot. All right. So this is part of what's going into Next15 is TurboPack is stable and you're shipping it with this. Was there a reason to couple the two or it just happened that way? Yeah, so we had TurboPack in Release Candidate for a long time. So when Jimmy mentioned the Release Candidate for Next.js was shipped six months ago, I think we had TurboPack in Release Candidate for even longer than that.
15:17And really the benchmark here for TurboPack was that we passed all development tests because we only shipped it for development so far. So it's coming for builds as well, as we're to note here. So in the end, you'll be able to run Next.build with TurboPack as well and have the same performance improvement, but it's still a work in progress because we have to add production optimizations and things like that. But yeah, on the coupling of the releases, we shipped a release candidate for Turbo Pack, but then the release candidate, that was the first time people actually started to try it out in their own apps as well.
15:49Up until that point, we have been using it for ForSell.com and our internal apps and things like that since October last year. So we already had it in production, in development for a while. And it was working great for us, right? But the big thing with Turbo Pack is that since it's a banner and it's going to touch all your code, so that's all your Node modules that you're importing, like all your first-party code that you wrote yourself and all that, it needs to be able to process every single edge case thing that you're using as well. A feature of the platform or feature of Node or a specific resolving thing that TypeScript supports or things like that.
16:28So we basically spent the last eight months, basically the bundle was already done for one and a half years, I think, at this point. It was really stable. The big thing here was getting all the tests to pass for NextGest, so we finished that in April. And then after that, we just spent time on book reports, testing out the top 300 packages that are used with NextGest, for example, trying it out on more open source apps and doing all the due diligence on making sure that we could actually confidently say this thing is going to work for your app if you don't customize your Webpack config. So the important thing to note here is that we allow you to customize your Webpack config.
17:06And that means that you can basically override any setting that is set in Webpack in XS internally, but we can't support that with TurboPack because TurboPack is not Webpack. Might sound like a no-brainer, but actually it's not as simple. So the easy explanation here is that we do support Webpack loaders in TurboPack, but we don't support Webpack plugins, for example. So if you add Webpack plugins, then you can't add those to TurboPack because we don't have the same low-level hooks and things like that. But we do support loaders. So if you just have a Webpack loader like SVGR or SVGR, I'm not sure what the right way to pronounce it is, but if you want to import SVGS components, for example, at the loader, that works with TurboPack as well.
17:49You can just add a TurboPack config for Webpack loaders. So that's your question around the timing. In the end, we spent a lot of time working towards a stable release. And then I think a month or two months ago, we finished all that work. So TurboPack for development was basically ready. We fixed all the linear issues that we had about it and all that. But then Nexus itself depends on TurboPack. So it actually has TurboPack as a dependency in a way. It compiles it in as a Rust binary. and in order to release it we had to ship it as part of like next just itself uh next just itself was in a release cycle where it was already in release candidate and was going out as next just 15 and like a month or like one half months later right so in the end like we like the timing is basically coincidental it could have been that it was like an earlier version as well or a later version depending on on when these guys went out and then the other thing to know here is that TurboPack and NextGes is actually not just TurboPack, the bundler.
18:53It's like the bundler itself. So that's like what we call TurboPack. And then the other part is the Rust bindings that we integrate with NextGes. So we add like all the NextGes specific ways that like layouts and pages are resolved and like custom transforms that we do for NextGes specifically, things like that. We call that like Next.rs internally because like we need to have some code name for it. But that's basically all the bindings into the bunder and how we add entry point, like routes basically to the bunder and things like that. So this gets to kind of an interesting topic around when you own your own build chain, which you now do as you're doing this.
19:33You can use it to make standard things faster because you happen to use them. Or you can even use it to start extending the language. frameworks like Svelte extend the language they own the compile chain or you get frameworks like Quick which also you know sets things up to be magical for you because it knows end-to-end what it's doing. Next as I understand it and particularly with things like OpenNext it's still just JavaScript and React but are you looking at extending it further now that you own your whole build chain so interesting i feel like one might say that next is in the same category as other frameworks you explain like if you think about it that from our perspective actually next is mostly all compiler based especially with like the new server components we introduced with the app rather it's now sort of like its own sub language you have well it's its own language and React one with like use client and use server.
20:32So like introduce new paradigms, we introduce use cache at Thursday at Conf. Those is React plus those things, which are to me really like an extension of the language already. It's not in the same way as Svelte or Quick in that way. So it's not like it's adding like a language extension where you have like specific directives that are special besides the directives like use cache and use client and use server. What is interesting there is that those are not JavaScript directives in a way. They're not actually directives that are saying this is different like syntax that allows you to do a certain thing.
21:11They're more like boundaries between the server and the client and they're like bundler marks. So they're more like, hey, like bundler now move to this different, like basically like move to this different environment. You can switch between environments using those directives. So you can say, like, use client. Now this is a browser slash like server set rendered component. And then like use server. This is now like something that runs on the server as well. So all of that is deep integration into like vendors already. So like we already had to do this with Webpack. We support it with Webpack as well.
21:47The main difference now is that with Webpack, it was like we had to do manual bookkeeping between like three different Webpack instances where there's basically three compilers running at the same time, whereas now it's one compiler that can reason about the entire mojo graph of all the different environments as well. To go back to the compiler work, I think maybe the difference in philosophy is that we try to still just be React and JavaScript. I don't think we're looking to go anywhere beyond that. But if React went for it, if they introduced their own.react file extension and then they had their own language where you would need to declare a use anywhere and it could have its own syntax, et cetera, we'd follow it for sure.
22:34But we don't have any other ambitions besides that. And to be fair, they already sort of did that with JSX, but it didn't introduce new semantics. It was more kind of sugar and easy use, but okay. It could be interesting though, if React did it, they could introduce their own flavor on it and make it so that you could use conditional hoops, all that kind of things. That'd be great. Let's maybe talk about some of the other functionality changes that, I mean, you mentioned you'd been making all of these improvements. And when we talked about initially, like a lot of what you mentioned was stability improvements, build improvements, things like that.
23:09But this is a major release. So there's got to be some sort of breaking features in there. And looking at it, the one that stood out to me in the release set was the async request APIs. Do you want to talk a little bit about that? What's the motivation? What are the implications of introducing that? Yeah, that was pretty fun. It was sort of like fairly risky on our end and we're like fairly, you know, wary of such a big change. For context, what we had before was through the app router, we exposed information about the current request through methods like cookies, headers, or we would inject like params or such params as like props to the server component that you would render.
23:51In 15, we decided to change those methods and functions to be accessible in the same way, but via promises instead. So calling headers would now return a promise, calling cookies would now return a promise, and you need to await it in order to read the content there. And so the 15 blog post goes a little bit into why we did that change, but it's kind of vague, basically. We didn't really say why we did it. And so we sort of uncovered that at Conf. What we've been looking to do with this change is to actually prepare for this new, like sort of like this other big change coming up in Next soon, which we call Dynamic I.O.
24:34internally. There's a lot of talks basically around Next.js complexity in the past, around like how the semantics around caching and like the static or the dynamicness of Next makes it hard for people to reason about. For context, we used to, what we still do, used to pre-render all pages by default. So you'd write a page and if it was a fetch call in there or anything really, we'd try to pre-render it at build time so that we could like optimize it and serve it in a static form. However, those changes were too, all this heuristic was a bit too strong sometimes and you would end up with people deploying their website and asking themselves why their website content was not changing if they had made a fetch call to a third-party API to display some content.
25:21So we had the semantic changes, and basically we ended up having to add a lot of configuration as well because some people wanted control over whether or not always needed to be dynamic or always wanted to be static or actually a mix of both. And it all made it a pretty hard learning experience, in my opinion. and I guess we're probably the only framework to do these kinds of optimizations. So anyway, we went back to the drawing board and we came up with this concept of dynamic I.O. where in order to simplify the learning experience, we wanted to come up with a single concept through which users could determine if their code was static or dynamic.
26:05And so dynamic I.O. is this. The gist of it is if your user code uses promises if you actually await for some asynchronous work then next can generally reason about it and say that this page should probably be dynamic so you don't have any problem anymore if you're doing file system reads if you're accessing your database because you know 99 of the case are probably dynamic here now you use next as you would if you write like a simple blog post and then you're just like reading content it's going to be static if you're like having a dashboard and you're fixing for your database it's probably going to be dynamic and so next can now reason more intelligently about which leads us to the cookies and headers changes if you think about it reading from the cookies or the headers actually makes the the request dynamic because it needs to be.
27:03It's actually about the in-commerce request that comes in. So you want to read it so that you can personalize it according to the user info. Is the user logged in or not? So implicitly, that's dynamic behavior. And so the real reason we made that change is so we could adapt it to this new dynamic IO behavior. Now it works the same. You await it, and now you're telling your page it's dynamic. So I think it makes sense. And so if I were to sort of rephrase back to you, you are doing, this actually gets back to the previous question around things you're doing with the build tools, right? So you are doing a build time step where you are optimizing things that can be generated statically to pre-generate them statically.
27:47So they go up there and you're trying to do that determination, quote unquote, automagically without having someone, the developer have to tell you things. and the simplest way to do that is say is there anything async going on here and so in order to do that then you had to take these things that maybe were using asynchronous api previously but actually technically should be asynchronous because they do depend on something dynamic something user request change them to be async and now your initial build time static analysis works across the board is that a fair summary yep that's perfect the only thing there is that it's not static analysis or like vanilla related per se it's more like we run the code and find that it's like basically at build this is where it gets complicated at build time so during next build we run the code and if the code then is doing anything async then we mark it as like this thing is not static it's dynamic analysis maybe yeah we actually internally we call the static the build phase like sort of like just plus processing for for doing runtime optimizations it's not static analysis in terms of analyzing the written code but it's pre-processed pre-run code is that right we try to call it pre-render for the most part so we try to pre-render during build and if it turns out that it's like doing anything async then we basically bail out from doing the full pre-render and there are some implications on like partial pre-rendering and all that as well that we maybe can talk about maybe not we can talk about that for hours probably but yeah it's like that like pre-render we try to generate that's the same in in x14 by the way like we do this pre-render but the mechanism is different so like when you call cookies it's a throwing mechanism instead of finding like promises makes sense all right other changes that are in next 15 you mentioned the next form component?
29:48Do you want to talk a little bit about that? So yeah, next form, really simple. So it's a drop-in for just a normal form tag, but it adds some additional features. So it adds prefetching, it adds client-set navigation. It allows you to do the things that you're very often already doing anyway, but it's quite cumbersome to manually handle. Or if you do manually handle it, think of this link component, for example. Link does a a bunch of features for you automatically that you could totally write yourself. You could write like an, is this thing in the viewport then writer.prefetch or something like that, but you really don't want to be spending time on that per se.
30:28And this is similar for next form where it will automatically do the prefetching for you. If it's a get route, for example, it just integrates better with like server functions and server actions. Yeah. A deal behind the component is that we wanted to make it as similar to the vanilla form as possible. And we just wanted to add a really thin layer that connects it to the Next.js router on its own. And we're not looking to doing anything fancy there. We're not integrating with form validation or anything you might expect from some other library. It's just supposed to be a really raw primitive so that you can get instant loading states if you're doing get form to another page, that kind of thing.
31:13it's like your search forms and things like that much easier to write those whereas today you you might have to like manually manage suspense and like adding transitions and a bunch of like things that are like slightly newer react as well so you know not everyone knows about them even so this just makes that the whole setup a bit easier so that gets into another thing that i wanted to talk about with you guys which is the relationship with react and in particular i saw that you're releasing against a an rc of react not even a stable released version what's the sort of thinking behind that what were there particular things you needed to get from that like how is that all working yeah it's pretty interesting question like for context we've been working you know really closely with the the react team at meta and we have so have a few members of the core team inside of our team as well.
Read the full transcript
32:09So generally the roadmap, the decisions around releasing React 19 are usually led by those members. And so the decision here, originally what happened is that back in May, React also released their release candidate, React 19, and basically we wanted to ship Next15 as part of that as well. So the idea was that we would release an RC and then fast follow on it. And so we made all the breaking change that we needed. We bumped the piracy and forced users on React 18 that were using the pages router, for example, to also upgrade to React 19. However, what happened is that a month later, there were some sort of discussions around one changing in particular regarding the suspended siblings rendering behavior in React 19.
33:02That was a big change for a lot of community users. And so the React team decided to hold the React 90 release on this, which is why we're still on the RC. So we ended up waiting on it for a while. But then we actually discussed with the React team internally. And we decided to opt for this strategy of releasing R-stable without blocking on the RC and this behavior changing. I think with the caveat that we would add backward compatibility to React 18 for the pages writer, so that, you know, sort of like separate concerns there. However, yeah, we got into like a slightly more complex situation with the app writer.
33:44Because one thing to know about the app writer is that we're building it off a vended version of React, which is, I think they call it Canary, Tim? Yeah. So AppRider always came with the actual latest version of React Canary, which is a version built for us, frameworks, like meta frameworks so that we could build on top of it so that we could integrate with the latest features before they actually hit the React table. So the reasoning here is that we've been on React 19 for basically a year or so already if you're using the AppRider. So the siblings, the suspend siblings change has shortened it like was actually has been present for over a year now for us.
34:30So we decided to not consider it a breaking change and we just started to move forward with it. Because per the React team itself, that's really the only change that's going to be shipped whenever the React 19 really ships as a GA. hey does next depend on that particular part of react 19 or is that just something separate so that if they ship a change to that it just doesn't bother you at all yeah it doesn't actually affect us it affects not to go into too much details but it affects like client-side suspense usage if they are doing fetching in rendering from the top of my mind so that basically means if you have two components that are in the same suspense boundary, what would happen previously is it would kick off the two components at the same time.
35:21So it would call render on both component A and component B if they're in the same suspense boundary. Now it actually will call component A. Once it's suspends, it will not render a component B. So that's a problem if you're using a library that is heavily relying on this. And as it turns out, there is quite a few of those in the whole React community. In our case, like the next chess, like the router in AppRouter is not using that pattern in like any way. The only thing where it might affect you in some ways if you're using lazy loading or things like that. But that's not super common per se.
36:01And yeah, so in practice, like we don't run into the same problem here. Because the fetching mechanism is different. And like if you're using server components, for example, like they don't run in the browser, so you didn't hit the same annotation. Basically at worst, it doesn't change anything for Next.js app router users since they always had it. And so whenever that gets fixed, it's going to be like a sort of like a minor performance optimization. Yeah, we'll only get better basically. That's the... Makes sense. This conversation brings me to another thing. I know there's been stuff out in the sort of web community questions around the deep interlocking relationship between the React team and the Next team now and thoughts about, oh, a server component's just for Next or how does that work and things like that.
36:50Kind of curious, how do you all think about the relationship of Next and React? Philosophically, what do you think, like what belongs in Next versus what needs to be in the React side? And then are there things even further out that shouldn't be in either of them and should be in a third-party library? Like, how do you think about those lines? There's a surprising amount of things that people think are Nexia-specific. They're actually React. A good example is useClient, useServer. Those are like React RFCs specific. Actually, like, I think the biggest misconception is that we invented useClient and useServer.
37:26That was actually not the case. That was based on, like, feedback from, like, other early adopters of server components, actually. So, like, for example, like, Hydrogen at Shopify was like one of the first frameworks to implement React server components even before we had like a full like working implementation. And that was even before we built AppRider, right? So they started like migrating apps and then they found like that they would run into problems with the extension. Like why didn't you add like.client.tsx or something like that? That's like a common feedback. But that was actually like something that the HydroDyn team found was like a very big problem to get overall community package adoption, for example, because it meant every single React library out there would have to change their code in some way.
38:11And there would be no way for you as a user to say, this is now a client component or things like that. But yeah, so I'm sure that Jimmy has a take on that for all like Nexus and React overlap. My personal take here is that we're trying to make, in the essence, like for me, I've been working on Nexus for so long. A lot of what we're doing now is actually bringing a lot of the learnings that we had from Next.js into the overall ecosystem. It's like a really good example of that is the head management, for example. Very first release of Next.js, like we had to work around this limitation of React, which is that you couldn't just inject tags into the head.
38:51So we had to create this like Next.head and it's like override, like build our own like React-ish thing that loops over JSX and tries to magically like inject it into the head. Over the last year or like the year before, so Josh on the React team for Cell, he spent so much time like figuring out like, can we bring something like this next head thing into React itself and bring it to all frameworks and like all users of React. So what this means is that you can now, with React 19, you can just write a meta tag in any component and it will just magically send it to the head for you automatically or write a title tag and it does the same thing.
39:30makes our lives easier because now we don't have to maintain this like brittle logic of trying to inject stuff into the head that React doesn't know about. And it makes everyone else's life better, including like Next.js users as well as everyone else by being able to inject like link tags, head or inject like link tags, meta tags, title, like that kind of thing. As well as like integrating those deeper into React, which is link tags can now integrate with Suspense and we can show a loading spinner until the link tag is loaded. and things like that. Stuff that I would never have been able to...
40:03We as a team would have never been able to add to NextGes even because we don't have full control over rendering which React does, right? So that's like one of the examples. I feel like one of the other examples is just the overall React server components, proving them out. And like I said, there was other teams like Hydrogen and some people building other frameworks on top of the React server components spec. But it's really helped to bring our expertise in how we were building service apps, bring that into React and give people all the things that you would ever need. So an example here is if you want to pass some data from...
40:43An example here is a limitation that Next has. Get service app props, you were never able to return a promise or return a date or a JSON object that would have been recursive, for example, or things like that. and React now has a serialization format that allows you to just return a JavaScript map and pass that to the browser from the server and it can serialize that and create a new map in the browser. Avoids iteration errors. It also is much more reliable when you have it in React itself. So there's a lot of benefits from being able to work with React team directly. The iteration errors is a good example of that as well.
41:24there is some like integration in next or you have to show the error overlay and things like that but really everyone's getting better hydration errors even if you're using other frameworks and other libraries as well one thing i want to touch on in particular is like we don't think about it just as next yes it's like when we design like server components etc like it has to all go back to react itself and you know in most of the mind of the people on team. If I'd say like, you know, it's rather like React pushes the next JS direction that we, whenever we design some changes, for example, we could have easily gotten our own NextJS dev tools that allow you to tap into server components and see what they're made of and like, you know, kept that for ourselves.
42:12Instead, we did the work to integrate it into the React dev tools so that any frameworks that will want to use server components will be able to tap into it. I think the awkward part maybe is that it's an insane investment of time on us on the Next.js team to realize the vision of server components to its fullest. And so that's why things haven't caught up on recently. We have a little bit of a head start here, but I'm really confident frameworks like Redwood have started exploring it. Remix also have been looking into it. And I'm looking very much forward to see what their spin on the server component is.
42:54As we talk about relationships with other community projects, and you said you're never designing it just for Next, you're pushing for React, which improves others. It leads me to another question I had, which is around the relationship between Next and Vercel. And I know there's historically even been a sense of, oh, we need a new project, OpenNext, in order to be able to build Next outside of Vercel. Jimmy, you mentioned before we got on the air that you're doing some work in that space. Do you want to share about it? Yeah. So we're really excited about this. I think as we were building up Next in the past few years, we were really focusing on making the best framework end-to-end as much as possible in terms of something that works really well in dev, but also works the best as you deploy it.
43:42we want to push for the best ways to build websites. And that doesn't just stop when you build it. It also matters how you deploy it, how you use best static content or how you organize your middleware. OpenX allows you to deploy Next.js easily on serverless platforms. But I do want to say that Next.js on its own has always been pretty easy to self-host easily. Tim can talk more about that, like the containerized mode where you could just run next start and that that always has been great but that's just limited on its own because you it will just allow you to have a simple like node server that will respond to sr requests and you run it like in your own instance or in your own five dollar vps that has sort of like always worked out of the box what has not worked real well out of the box is really that next yes story as a as an infrastructure basically the framework defined infrastructure structure as being like next.js is telling the provider, like doesn't matter if it's for cell or some other provider, like this is the serverless function I want you to create.
44:49And this is the route rules I want you to create. This is where the static files are, but the static files also need to have some headers, for example. All of that is like baked into next start. So that's the node.js production server or custom server if you're using that. And so basically all those rules are there right so it has the the right static catching headers and things like that if you're building a serverless platform then you would have to figure that out manually basically because the all these platforms have different formats right so there's not just like one standardized output for for all of these and that's like where things like open next for example and like serverless next yes i think it's like one of the names of the other packages and things like that they they are trying to create like these are the serverless functions these are the route rules and then generate the route rules for like a specific service so that could be like aws or azure or gcp or anything like that and then like if you're using next start for example like you you do have to like once you're starting to scale so it's like beyond one instance of the next server most people run thousands if not like a hundred thousand plus of those depending on like the amount of containers that you're generating basically the thing is like we see a very large websites like self-hosting on next start or no just server as well so it's just that you have to use serverless per se like nexus runs totally fine on the server like jimmy said it requires some extra setup and like that setup was there it just never explicitly documented and like this is exactly how you do it type thing and that's what's changing so i guess that jimmy can talk a bit more about that yeah so on one hand we're like we're making sure like the documentation gets better around that side we're going to update the docs soon with like you know those examples we talked about we were going to show you you know the really simple steps of like how you could deploy on like i think literally all of the providers you could think of but what we're doing as well is working with the open next maintainers which are great by the way in order to change the way next.js is architecture itself so that we can better we can avoid you know in theory having something like open next existing by taking their learnings and adapting it into our code base so that it then other providers you know Netfile, Cloudflare, AWS can consume its outputs and ship that framework-defined infrastructure as easily as we can.
47:26I think the tension was around, if you want to do that right now, the OpenX maintainers, they had to reverse engineer our code base. But if it's all in the open, it's also, you know, the contracts are a bit unclear. The outputs are subject to change. And yeah, we can do a better job at documenting and at creating and enforcing a standard behavior there. So yeah, I'm really excited about this line of work. I think we want NextGest to be the best as possible on every platform as we can. And we're investing a lot of time into creating a set of community maintainers there. And we want to make sure we support everyone in the community in that regard.
48:08And we just want to make sure that when you're self-hosting, that that's not a bad thing, right? So there's really, obviously we'd love for you to use Vercel and there's many reasons to use Vercel, but that it would be the only place to host NextGes is definitely not one of our goals. It's more about making sure that everyone can succeed with NextGes. Day-to-day, if you're using Vercel, great. If you're not using Vercel, great as well. And there's many other reasons to use Vercel, in my opinion as well, like preview deployments, things like that. so it'll be exciting to see like where this whole effort turns out because we just launched the new GitHub org that has all these like starter templates as well various different providers serverless providers as well and and some of them they only support like static for example so like say you only you don't even have a server like you don't want to use next start you want to use next export for example or like the output export then we have a starter kit for that as well Awesome.
49:07Well, I think we have run through our time here. Thank you, gentlemen. This has been great. Any last thing you want to leave our listeners with? If you upgrade it to Nexus 15, you're not done yet and try to run through it back as well. It's opt-in still. And the reason for that is that we don't have builds yet. But what we've seen in our own apps and people reaching out to us is definitely going to give you a big performance boost for development. So like you said, just faster iteration velocity, basically for everyone.
From the publisher
Next.js is an open source JavaScript framework developed by Vercel. It’s built on top of React and is designed to streamline web application development using server-side rendering and static site generation. The framework’s handling of both frontend and backend tasks, along with features like API routes and file-based routing, have made it an increasingly popular
The post Next.js 15 with Jimmy Lai and Tim Neutkens appeared first on Software Engineering Daily.
