
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.
Loading summary
Host
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 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. They join the show to talk about Next JS and what's new in version 15. Kevin Ball, or K. Ball, 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 K. Ball on Twitter or LinkedIn or visit his website Kball LLC.
Kevin Ball
Hey guys, welcome to the show.
Tim Newkins
Hey, thanks for having us.
Kevin Ball
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?
Jimmy Lai
Yeah. So my name is Jimmy. I'm a French software engineer. Before Vercel I used to work at Meta in London. Used to work on React Native and on some internal products. Used to work a lot on web performance and everything 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. The mission, Guillermo's mission really struck me there in terms of like bringing like the amazing technologies we added thanks to other companies. I didn't start working on Next when I joined I used to work on the feature Flex but I quickly joined the team back in was it end of like 2022 and ever since I've been working mostly on the app router. A year ago I started managing the team and we've like handled mostly the 15 release and a lot of the great work the team has completed in the version 14.1. 14.2. Yeah, that's it on me.
Kevin Ball
Awesome. How about you Tim?
Tim Newkins
Hey, I'm Tim. I've been working on Nextels for a while since like 2016 when it first came out as A contributor and eventually joined Vercel in 2017. And since then I've been building quite a lot of different things, but mostly working on Next jets across all of them and, like, building out the team. And now I'm tech lead for Next jets and turbopack. Mostly focused on turbopack nowadays and trying to get that over the line and into the hands of everyone.
Kevin Ball
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?
Jimmy Lai
Yeah. So this release has been a long time coming, actually. For those not familiar with the reschedule, we used to drop, like, really regularly in the past year. After we shipped apprauter with next 13, we were like, really following up on it every month so. With 15, 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 it 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 Next JS form component or the after hooks, which allows you to tap into the request lifecycle. And we also improved so much on the TurboPack development story, which to me, I think is actually maybe the biggest headline for next 15. TurboPack is now stable for development. Maybe Tim can say more about it as well.
Tim Newkins
Yeah, there's definitely been 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 there's definitely been a strong shift in focus towards stability improvement. 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. Those errors, we just saw that everyone was struggling with them. We were struggling with them ourselves as well. Inside of Vercel, it was just not clear where and what it was causing it. Right. So what code and 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 that React can actually show this is a diff, basically for 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 small tweaks that may seem like very small stuff, but in the end, it's affecting a million developers every day because it just makes it easier to solve your iteration errors or some other errors that didn't have correct source mapping or things like that. So that's just on the Nexus 15 side of things. And then as part of Nexus 15, we're also shipping TurboPack for development. So TurboPack is like the new underlying compiler and builder for Next js. And we're planning to make it more like a generic bundler in the future. But right now we're just focusing it on Next JS because that's like the largest service area. And once that works well for, and once it works well for Next JS and it can build all the dependencies that we see people use every day, then it will be a really good generic solution already as well. And so we're first focusing on. First we focused 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, or when you make a change, it would take like seconds sometimes before you can see it on screen, be it like CSS changes or code changes. So basically we set out to build a faster solution what Next JS had up till that point. So we built this new architecture to really scale to the large amounts of code that we see nowadays. So when I started working on XSH eight years ago, JavaScript apps were certainly not small. And the node modules meme has always been true a little bit. But I would say the bottomless pit has gotten a lot more bottomless in the recent years. What we basically see is that there's more consolidation of libraries. And that's not bad at all, really. It is really nice. So you see more icon libraries, more design systems that are just out of the box, have everything that you need, right? So previously where you would have to go and write 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 like 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. And basically what that meant for us is that in practice what we'd see is we'd see smaller apps get over 10,000 modules where previously that was not the case. Or in some exotic cases where you accidentally import five different icon libraries that all export 10,000 modules, you'd see through 30,000 plus modules for something that seems to be a simple case. And when I say modules, I don't.
Jimmy Lai
Mean it's the great NPM inflation.
Tim Newkins
Basically, yeah, there's some libraries that ship icons that have multiple icon libraries, so you can pick and choose between 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 it a lot. And it's not a bad thing. Like I said, 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 still have tree shaking and all that. But from the compiler and blender level, we first need to know about everything that exists before we can actually shake them. And that causes the compiler to take longer, even if you only use one icon from this icon library. So that's why we set out to build a new compiler in bundler that can scale up with these high demands of larger apps. And then besides that, also our own Vercel's internal app for vercel.com, for example, started growing quite a lot as well. We added hundreds of engineers at Vercel, so there's just 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. So that turned into turbopack eventually. We basically investigate all different kinds of solutions, but found that it doesn't really fit with the way that Next JS 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 10 years at least, and we can still optimize further as well. So where we're at today is this is just a start, right? So we're at a certain performance that's much better than the previous compiler, but the current performance of the new compiler is still only at a certain point where we still are not super. 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.
Kevin Ball
So 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 like vite and rollup or something like that.
Tim Newkins
Exactly, yeah.
Jimmy Lai
I think what we found, yeah, like Tim said, building on webpack is just that we were sort of like architecturally limited. We, like. I actually don't remember how old this webpack is, probably, you know, around 10 years old.
Tim Newkins
Tim, it's over 10 years. Yeah, yeah.
Jimmy Lai
And so the whole structure, the whole amount of legacy had supported 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? Like, you know, we considered. Obviously that's going to be a question. 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. Like, 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 was I was really impressed talking with Tobias about it at the last conf, is now that we build the bundler in mind with the idea that you can separate each of the tasks that it does and cache them individually at the function level instead of like at the module level. This allows us to like avoid repeating any work that we don't need to do. First off, that we can see that from the HMR performance boost, which is like sort of like mind blowing, you hit command save on a file and it just, you know, it feels like magic to me.
Tim Newkins
Yeah, we found that it's 95% faster than what it was before. So it would take. One example is like on one page on Vercel's own app, it's taken like 900 milliseconds and it went down to I think like 45 milliseconds for the exact same change. Right, so like changing some css, for example. Exactly, yeah. One of the problems that webpack had is, or still has in general is that the moment you start, 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, the moment you have like over 10,000 to 30,000 modules, there's just an inherent overhead on processing hot 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. So that means if you're writing CSS and you don't have any customization, so you don't add post CSS or tailwind or anything like that, we only have to recompile that single file instead of recompiling the entire module graph or the entire chunks. Are JavaScript files output, for example, or C files output. We don't have to recalculate those, we only have to recalculate the pods that's affected by that change, basically.
Kevin Ball
Well, and that amount of timing change is a real difference for your dev cycle, right? 900 milliseconds is still not massively long. But 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. Right? Is that right? It's like using dev tools essentially, except you're using your code base.
Tim Newkins
Yeah, yeah, yeah.
Jimmy Lai
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 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 like saving it, you know, in your session, we could save it across forever? Like on all of your session, you stop dev server, you go to sleep, you wake up the day after tomorrow and you can pick up exactly where you left off in like hundreds of milliseconds. That's a lot of time saved.
Kevin Ball
That is A lot. All right, so this is part of what's going into next 15 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?
Tim Newkins
Yeah. So we had TurboPack in release Canada for a long time. So when Jimmy mentioned like the release candidate for next JS was shipped 6 months ago, I think we had turbo pack in the release candidate for even longer than that. And really like the benchmark here for turbopack was that we pass all development tests because we only shipped it for development so far. So it's coming for builds as well as important 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 TurboPack, but then the release candidate, that was the first time people actually started to try it out in their own apps as well. Up until that point, we have been using it for vercel.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 TurboPack is that since it's a bunner 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 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. So we basically spent the last eight months, basically the bundler was already done for one half years. I think at this point it was really stable. The big thing here was getting all the tests to pass for Next js. So we finished that in April and then after that we just spend time on buck reports testing out the top 300 packages that are used with Next JS, 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 and that means that you can basically override any setting that is set in Webpack, in Excel 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, things like that. But we do support loader. So if you just have a wephic 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 Trofec as well, you can just add a servo pack config for webcloaders. So to answer your question around the timing, in the end we spent a lot of time working towards a stable release and then I think like a month or two months ago we finished all that work. So Turbac for development was basically ready. Like we fixed all the linear issues that we had about it and all that. But then next JS itself depends on TurboPack, right? So it actually had 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 JS itself. Next JS itself was in a release cycle where it was already in a release candidate and was going out as Nexus 15 and like a month or one half months later. Right. So in the end the timing is basically coincidental. It could have been that it was an earlier version as well, or a later version, depending on when these guys went out. And then the other thing to know here is that throwback in Next Jazz is actually not just throwback the bundler, it'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 Next js. So we add all the Next js specific ways that layouts and pages are resolved and custom transforms that we do for Next js specifically, things like that, we call that Next RS internally because we need to have some code name for it, but that's basically all the bindings into the bundler and like how we add entry point like routes basically to the bundler and things like that. Yeah.
Kevin Ball
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, you 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 Qwik, which also 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 Open Next is still just JavaScript and react, but are you looking at extending it further now that you own your whole build chain?
Jimmy Lai
So interesting. I feel like one might say that Next JS is in the same category as other frameworks you explain. Like, if you think about it from our perspective, actually Next JS is mostly all compiler based, especially with like the new server components we introduced with the app Router. It's now sort of like its own sub language you have. Well, it's its own language in React 1 with like use Client and Use Server. So like introduce new paradigms. We introduce use Cache at Thursday at conf DOS is React plus those things which are to me really like an extension of the language already.
Tim Newkins
It's not in the same way as Svelte or Qwik in that way. So it's not like it's adding a language extension where you have specific directives that are special besides the directives like usecache and useclient and useserver. 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 syntax that allows you to do a certain thing. They're more like boundaries between the server and the client. And they're like Bundler marks. So they're more like, hey, bundler. Now move to this different. Basically move to this different environment. You can switch between environments using those directives. So you can say use Client. Now this is a browser server side rendered component and then use Server. This is now something that runs on the server as well. So all of that is deep integration into vendors already. So we already had to do this with webpack. We support it with webpack as well. The main difference now is that with webpack we have to do manual bookkeeping between 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 like module graph of like, all the different environments as well.
Jimmy Lai
To go back to the compiler work, I think maybe, yeah, 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 like React file extension and they had their own language where you could look, you would need to to declare a use anywhere and it could have its own syntax, et cetera, we'd follow it for sure. But we don't have any other ambitions besides that.
Kevin Ball
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.
Jimmy Lai
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 hooks, all those kind of things. That'd be great.
Kevin Ball
This episode of Software Engineering Daily is brought to you by leanware. Struggling with development teams that say yes to everything but deliver on nothing, leanware offers a refreshing approach. They're a Colombia based team delivering top tier software development with full transparency and world class engineering standards. They've honed their craft over nearly five years, sticking to technologies where they have senior expertise. This means no compromises on quality, ever. Their C level executives are always accessible. Ensuring seamless communication and a genuine partnership. Plus being in a similar time zone to the US makes collaboration effortless. Don't settle for less. Partner with leanware for software development done reliably. Visit leanware Co or see the show notes to get started. That's leanware Co. Leanware redefining software development with exceptional quality and realistic expectations. 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. But this is a major release, so there's gotta 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 wanna talk a little bit about that? What's the motivation? What are the implications of introducing that?
Jimmy Lai
Yeah, that one was pretty funny. It was sort of like fairly risky on our end and we're like fairly 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 search params as like props to the server component that you would render in 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 like 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 IO internally. 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 is we used to what we still do is 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 tried to pre render it at build time so that we could 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. So we had the semantic changes and like basically we ended up having to add a lot of configuration as well because some people wanted control over like 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 either way we went back to the drawing board and we came up with this concept of dynamic IO 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. And so Dynamic IO 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 cases are probably dynamic here. Now you use NEXT JS as you would if you write like a simple blog post. And 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 request enemy because it needs to be. It'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 I O behavior. Now it works the same, you await it and now you're telling your page it's dynamic.
Kevin Ball
So I think it makes sense. So if I were to 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. So 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?
Jimmy Lai
Yep, that's perfect.
Tim Newkins
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 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 a.
Jimmy Lai
Static, it's dynamic analysis. Maybe. Yeah, we actually internally we call the static the build phase. Like sort of like just post processing for doing runtime optimizations.
Kevin Ball
It's not static analysis in terms of analyzing the written code, but it's pre processed, pre run code. Is that right?
Tim Newkins
We tried to call it prerender for the most part. So we tried 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 parser prerendering 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 prerender we tried to generate that's the same in x14 by the way. We do this prerender but the mechanism is different when you call cookies, it's a throwing mechanism instead of finding promises.
Kevin Ball
Makes sense. All right. Other changes that are in next 15 mentioned the next form component. Do you want to talk a little bit about that?
Tim Newkins
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, adds client set navigation. Like it allows you to do the things that you're very often already doing anyway, but it's like quite cumbersome to manually handle. Or if you do manually handle it, think of this LINQ component for example. LINQ does a bunch of features for you automatically that you could totally write yourself. You could write 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. And 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.
Jimmy Lai
Yeah, idea behind the component is that we wanted to make it as similar to the vanilla form as possible and we just wanted to add like a really thin layer that connects it to the next JS router on its own. And like we're not looking to doing anything fancy there. We're not doing like, we're not integrating with like form validation or anything you might expect from some other library. It's just supposed to be like a. 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.
Tim Newkins
It's like your search forms and things like that. Much easier to write those. Whereas today you might have to manually manage suspends and adding transitions and a bunch of things that are slightly new in React as well. So not everyone knows about them even. And this just makes that whole setup a bit easier.
Host
This episode of Software Engineering Daily is brought to you by Jellyfish, the software engineering intelligence platform. Powered by a patented allocations model and boasting the industry's largest customer dataset. You know, one of the biggest shifts in the past year or so is the adoption of Gen AI coding tools like GitHub, Copilot and engineering leaders are trying to figure out if their teams are actually using it, how much they're using it, and how it's affecting the business. Are they shipping more? Is more Roadmap work being done? How do you know beyond anecdotes and surveys? That's why Jellyfish introduced the Copilot dashboard in 2024 in partnership with GitHub, and since then they've analyzed data from more than 4,200 developers at more than 200 companies. Want to know an interesting finding? Developers are shipping 20.9% more with Copilot. The folks at Jellyfish have a ton more insights and you can get started seeing your own team's data so you can plan and manage better. Learn more at Jellyfish Copilot today.
Kevin Ball
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 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?
Jimmy Lai
Yeah, it's a pretty interesting question. Like for context, we've been working really closely with the React team at Meta, and we also have a few members of the core team inside of our team as well. So 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 next 15 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 peer PENC 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, you know, a month later there were some sort of discussions around like one change in in particular regarding the suspended siblings rendering behavior in React 19. That was a big change for a lot of community users that the and so the React team decided to hold the React 19 release on this, which is why we're still on the rc. So we ended up like waiting on it for a while, but then we actually discussed with the the React team internally and we decided to opt for this strategy of like releasing rstable 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 router so that, you know, sort of like separate concerns there. However, yeah, we got into like a slightly more complex situation with the app router because one thing to know about the app router is that we're building it off of a vendored version of React which is, I think they call it Canary. Tim. Yeah, so appwriter always came with the actual latest version of React Canary, which is a version built for like 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 reaction stable. So the reasoning here is that we were. We've always, we've been on React 19 for basically a year or so already if you're using the app rather. So the siblings, the Suspense Siblings change as a shortened like was actually has been present for over over a year now for us. So we decided to not consider it a breaking change and we decided 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 release chips as GA.
Kevin Ball
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?
Tim Newkins
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. So 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 suspend, it will not render 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's quite a few of those in the whole React community. In our case, the next js, the router in App Router is not using that pattern in any way. The only thing where it might affect you in some way is if you're using lazy loading or things like that. But that's not super common per se in practice. We don't ran into the same problem here because the fetching mechanism is different. If you're using server components, for example, they don't run in the browser so you don't hit the same limitation basically.
Jimmy Lai
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 a minor performance optimization.
Tim Newkins
Yeah, we'll only get better, basically.
Kevin Ball
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 is just for Next or how does that work and things like that. Kind of curious. How do you all think about the relationship of Next and React philosophically, what do you think? 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? How do you think about those lines?
Tim Newkins
There's a surprising amount of things that people think are next to specific. They're actually React. A good example is Use Client, Use Server. Those are like React RFCs, specific actually. But the biggest misconception is that we invented Use Client and Use Server. That was actually not the case. That was based on feedback from other early adopters of server components, actually. So, for example, Hydrogen at Shopify was one of the first frameworks to implement React Server components even before we had a full working implementation. And that was even before you built App Router. So they started 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? It's like a common feedback. But that was actually something that the Hydrodynam 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 and 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 the Next JS and React overlap. My personal take here is that we're trying to make in the essence 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, we had to work around this limitation of React, which is that you couldn't just inject tags into the head. So we had to create this next head and basically override build our own React ish thing that loops over JSX and tries to magically inject that into the head over the last year or the year before. So Josh on the React team Vercel, he spent so much time figuring out, 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. Makes our lives easier because now we don't have to maintain this brittle logic of trying to inject stuff into the hat that React doesn't know about. And it makes everyone else's life better, including Next JS users as well as everyone else, by being able to inject like link tags, head tags, 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, we as a team would have never been able to add to Next JS even because we don't have full control over rendering, which React does. Right? So that's like one of the examples. I think 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 component spec. But it's really helped to bring our expertise in how we were building server side apps, bring that into React and give people all the things that you would ever need. Right. So an example here is, if you want to parse some data from an example, here is like a limitation that next has GetServiceProps. You were never able to return a promise or return a date, or like 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, avoid saturation 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. Hydration errors is a good example of that as well. There is some integration index 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.
Jimmy Lai
One thing I wanted to touch on in particular is like, we don't think about it just as Next js. It's like when we design server components, et cetera, it has to all go back to React itself. And in most of the mind of the people on team, let's say it's rather React pushes the Next JS direction whenever we design some changes. For example, we could have easily gotten our own Next JS 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. Instead, we did the work to integrate into the React devtools 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 that's why things haven't caught up on recently. We have a little bit of a head start there, but I'm, you know, really confident, like frameworks like Redwood have started exploring it. Remix also have been looking into it and I actually look, I'm looking very much forward to see what, you know, what their spin on server component is.
Kevin Ball
As we talk about sort of 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 open NEXT 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?
Jimmy Lai
Yeah. 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 like, you know, the sort of Best framework end to end as much as possible. Like in terms of like something that works really well on dev, but also works the best as you deploy it. We 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, it's best served 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 on that. A containerized mode where you could just run nextart and that always has been great. But that's just limited on its own because it'll just allow you to have a simple node server that will respond to SSR requests and you run it in your own instance or in your own $5 VPs. That has sort of always worked out of the box. What has not worked real well out of the box is really that Next JS story as an infrastructure.
Tim Newkins
Basically the framework defined infrastructure as being like Next JS is telling the provider like doesn't matter if it's Vercel or some other provider. Like this is the serverless function I want you to create and 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 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 right static caching headers and things like that. If you're building a serverless platform, then you would have to figure that out manually basically because all these platforms have different formats, right? So there's not just like one standardized output for all of these. And that's like where things like Open Next for example, and Serverless Next JS I think is one of the names of the other packages and things like that they are trying to create. These are the serverless functions, these are the route rules. And then generate the route rules for a specific service. So that could be AWS or Azure or GCP or anything like that. And then if you're using NextStart for example, you do have to once you're starting to scale so it's beyond one instance of the Next server. Most people run Thousands if not 100,000 plus of those depending on the amount of containers that you're generating. Basically the thing is we see very large websites like self hosting on NextStart or NodeJS server as well. So just that you have to use serverless per se. Nexus runs totally fine on the server. Like Jimmy said, it requires some extra setup and 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 Jimmy can talk a bit more about that.
Jimmy Lai
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 the really simple steps on 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 architectured itself so that we can better, we can avoid, you know, in theory having something like Open X existing by taking their learnings and adapting it into our code base so that it then other providers, you know, Netflix, Cloudflare, aws can consume its outputs and ship that framework defined infrastructure as easily as we can. I think the tension was around if you want to do that right now, the OpenX maintainers, they had to rehearse engineer our code base quite a bit. It's all in the open, but also, you know, the contracts are a bit unclear, the outputs are subject to change. And yeah, we can, we can do a better job at documenting and creating and enforcing a standard behavior there. So yeah, I'm really excited. But this line of work, I think we want Next JS 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.
Tim Newkins
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 Next JS is definitely not one of our goals. It's more about making sure that everyone can succeed with Next JS 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 where this whole effort turns out because we just launched the new GitHub. Org has all these starter templates as well, various different providers, serverless providers as well. And some of them they only support static for example, so you don't even have a server. You don't want to use Next Start, you want to use Next Export for example, or the Output Export. Then we have a starter kit for that as well.
Kevin Ball
Awesome. Well, 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.
Tim Newkins
To Nexus 15, you're not done yet and try to render it back as well. It's opt in still and the reason for that is that we don't have built 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.
Software Engineering Daily: Next.js 15 with Jimmy Lai and Tim Neutkens
Release Date: December 5, 2024
Host: Kevin Ball
Guests: Jimmy Lai (Software Engineering Manager at Next.js) and Tim Neutkens (Tech Lead for Next.js and TurboPack)
In this episode of Software Engineering Daily, host Kevin Ball sits down with Jimmy Lai and Tim Neutkens from the Next.js team to delve into the substantial updates introduced in Next.js 15. Released in October 2024, this latest version brings significant enhancements aimed at improving performance, stability, and developer experience. The discussion covers the integration of TurboPack, new async request APIs, the Next Form component, and the evolving relationship between Next.js and React.
Kevin Ball opens the conversation by highlighting the anticipation surrounding the Next.js 15 release:
[03:16] Jimmy Lai: "This release has been a long time coming... we decided to take 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."
Key Highlights:
after hooks for tapping into the request lifecycle.A central theme of the discussion is TurboPack, Next.js's new bundler and compiler designed to replace Webpack and similar tools.
Tim Neutkens elaborates on TurboPack’s role and benefits:
[04:33] Tim Neutkens: "TurboPack is now stable for development... we’re focused on TurboPack for Next.js because that's the largest service area."
Key Points:
Performance Boosts: TurboPack offers a 95% improvement in Hot Module Replacement (HMR) performance, reducing update times from 900ms to 45ms in certain scenarios.
[12:05] Tim Neutkens: "It's 95% faster than what it was before... changing some CSS, for example."
Scalability: Designed to handle large codebases efficiently, managing upwards of 30,000 modules without significant performance degradation.
Caching Enhancements: Introduction of persistent disk caching allows developers to resume work quickly after stopping and restarting the dev server.
[14:03] Jimmy Lai: "What if we could just persist all of that work now to the disk cache?... you can pick up exactly where you left off in like hundreds of milliseconds."
Transition from Webpack: TurboPack serves as a modern alternative to Webpack, Vite, and Rollup, overcoming architectural limitations inherent in older bundlers.
[10:18] Kevin Ball: "So just to make sure, I understand this is replacing what you were using webpack for..."
Next.js 15 introduces async request APIs, a significant change aimed at streamlining how asynchronous data fetching is handled within the framework.
Jimmy Lai explains the motivation behind this change:
[24:11] Jimmy Lai: "...we wanted to come up with a single concept through which users could determine if their code was static or dynamic."
Key Points:
Promises for Request Data: Methods like headers and cookies now return promises, requiring developers to await their resolution.
[24:11] Jimmy Lai: "Calling headers would now return like a promise. Calling cookies would now return a promise..."
Dynamic IO Concept: Introduced to simplify the framework's ability to distinguish between static and dynamic content based on asynchronous operations.
[24:11] Jimmy Lai: "Dynamic IO is this... 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."
Enhanced Pre-rendering: Next.js can now intelligently pre-render pages at build time, defaulting to static rendering unless asynchronous operations indicate dynamic content.
[29:09] Jimmy Lai: "Yep, that's perfect."
Another noteworthy addition in Next.js 15 is the Next Form component, designed to simplify form handling within applications.
Tim Neutkens discusses its functionality:
[30:36] Tim Neutkens: "Next form really simple... it adds some additional features like prefetching and client-side navigation."
Key Points:
Seamless Integration: Acts as a drop-in replacement for the standard <form> tag, automatically handling features like prefetching and navigation transitions.
Developer Convenience: Reduces the need for manual handling of common form-related tasks, streamlining the development process.
[31:27] Jimmy Lai: "The idea behind the component is that we wanted to make it as similar to the vanilla form as possible... just add a really thin layer that connects it to the Next.js router on its own."
A significant portion of the discussion revolves around the evolving relationship between Next.js and React, especially concerning upcoming React 19 features.
Tim Neutkens sheds light on how Next.js integrates with React’s advancements:
[38:51] Tim Neutkens: "We're trying to make in essence... 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."
Key Points:
Collaborative Development: Close collaboration with the React team ensures that Next.js stays aligned with React’s roadmap and leverages its latest features.
Server Components and Directives: Next.js utilizes React’s useClient, useServer, and useCache directives to manage server and client boundaries effectively.
[38:09] Tim Neutkens: "...we support it with webpack as well. The main difference now is that with webpack we have to do manual bookkeeping between three different webpack instances... whereas now it's one compiler that can reason about the entire module graph."
Enhancing React Features: Contributions such as improved head management and hydration error reporting benefit the broader React community.
[43:15] Jimmy Lai: "We don't think about it just as Next.js... When we design server components, etc., it has to all go back to React itself."
The conversation also touches on deploying Next.js applications, particularly the relationship with Vercel and efforts to support diverse hosting environments.
Jimmy Lai and Tim Neutkens discuss the challenges and solutions for deploying Next.js outside Vercel:
[45:03] Jimmy Lai: "Next.js on its own has always been pretty easy to self-host... but what's not worked real well out of the box is really that Next.js story as an infrastructure."
Key Points:
OpenX Initiative: Working with the Open Next maintainers to standardize deployment processes across various platforms, making it easier to deploy Next.js applications on providers like AWS, Azure, and GCP.
[48:18] Jimmy Lai: "...we can better avoid something like OpenX existing by taking their learnings and adapting it into our code base..."
Documentation and Community Support: Efforts to enhance documentation and provide starter templates to simplify deployments on different hosting platforms.
[46:16] Tim Neutkens: "...we're investing a lot of time into creating a set of community maintainers and we want to make sure we support everyone in the community in that regard."
Self-Hosting Flexibility: While Vercel remains the optimal choice for seamless integration, Next.js 15 ensures robust support for self-hosted environments without compromising performance.
[49:50] Tim Neutkens: "We just want to make sure that when you're self-hosting that's not a bad thing."
As the episode wraps up, Tim Neutkens emphasizes that upgrading to Next.js 15 is just the beginning:
[50:58] Tim Neutkens: "To Next.js 15, you're not done yet and try to render it back as well. It's opt-in still and the reason for that is that we don't have built 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."
Final Takeaways:
Next.js 15 marks a significant leap forward for developers, introducing TurboPack, async request APIs, and the Next Form component, all aimed at enhancing performance and developer experience. The strong collaboration with the React team ensures that Next.js remains aligned with the latest advancements in the ecosystem. Additionally, efforts to streamline deployment across various platforms underscore Next.js's commitment to flexibility and scalability. As Jimmy Lai and Tim Neutkens highlight, Next.js 15 is both a culmination of extensive development and a foundation for future innovations in web application development.
Note: This summary excludes advertisements and non-content sections from the original transcript to maintain focus on the core discussion.