Podchaser Logo
Home
785: What’s Next for Next.js with Tim Neutkens

785: What’s Next for Next.js with Tim Neutkens

Released Friday, 21st June 2024
 1 person rated this episode
785: What’s Next for Next.js with Tim Neutkens

785: What’s Next for Next.js with Tim Neutkens

785: What’s Next for Next.js with Tim Neutkens

785: What’s Next for Next.js with Tim Neutkens

Friday, 21st June 2024
 1 person rated this episode
Rate Episode

Episode Transcript

Transcripts are displayed as originally observed. Some content, including advertisements may have changed.

Use Ctrl + F to search

0:00

Welcome to syntax today. We have Tim

0:02

note cans on from Vercel. Next.

0:05

Yes. Co-author of next. She has to talk

0:07

to us all about everything that's

0:10

going on with React with next. She

0:12

has 15 with server components with react

0:14

compiler with turbo pack, kind of a

0:16

lot going on in the whole, this

0:19

whole space recently. So I thought like,

0:21

let's bring them on to talk about

0:23

it. So welcome, Tim. Thanks so

0:25

much for coming on. Yeah. Thanks for having me.

0:28

Where should we start this off? Um, yeah,

0:30

well, I mean, we could start off with

0:32

some of the, the hottest new stuff, which

0:34

I guess compiler. So, you know, I guess

0:37

first and foremost, I know,

0:39

I know, you know, this is a react thing and not

0:41

a next JS thing, but I'm sure

0:43

you all are very tightly integrated into

0:46

this, what does the react

0:48

compiler do for those people who might not be aware

0:50

of what it is and what it does? Yeah.

0:54

So, um, if you

0:56

watch the recent ReactConf keynote,

0:58

um, if you haven't watched

1:00

it, I'd highly recommend you to watch it because

1:02

it's definitely a much better explanation than I will

1:04

ever be able to do, I think. Yeah.

1:07

But in essence, it's like, um, in

1:09

like 2018 React hooks were introduced. Um,

1:11

there were a whole lot of hooks,

1:14

right? So like, uh, use state, use

1:16

memo, uh, the kind of thing. But

1:18

really like in the end, like that

1:21

didn't have the ergonomics that you want. Uh, eventually

1:23

like when you're writing this code, so they

1:25

were like created in a way that you can

1:28

like incrementally get rid of them if you were to

1:30

build a compiler, uh, at some

1:32

point, that's really what the React

1:35

team did. So they went ahead on

1:37

like a pretty long journey. I'm

1:39

not sure exactly like how long they've

1:41

been working on it exactly. Many years,

1:43

I think. Yeah. Something like four years,

1:45

which, uh, which also causes like people

1:47

to dab, like we'll ever like come,

1:49

right? Like, uh, are we ever

1:51

going to have suspense? Like that kind of thing,

1:53

right? Um, but now

1:56

in the last, you know, like two, three weeks

1:58

ago, um, they, they now. that

2:00

the React compiler is now both

2:03

open source, so you can view the source

2:05

code. And it's in

2:08

beta, so you can try it out. They

2:10

didn't recommend you to ship it to production

2:12

yet, but they are shipping it to production

2:14

themselves in Instagram and

2:17

in other places at meta

2:20

to really dog food the

2:22

system. That

2:25

gives you exposure to a lot of different types

2:27

of code, right? So it's similar to any time

2:30

you start building a compiler that transforms

2:32

the original source code into something else,

2:35

there are really edge cases and they're

2:37

trying to catch all these edge cases.

2:39

So that's why it's released early, so

2:42

people can try it out. And we're like, what is it?

2:45

That's the initial question. It

2:47

basically does memoization for you automatically.

2:51

And not just for the basic

2:53

cases, I have a value that

2:55

is derived based on some state or

2:57

some... Basically

2:59

the things that you would usually call use memo

3:01

for, that kind of thing. Those

3:04

are the things that I can, having

3:06

some re-acknowledge, I can manually add

3:08

them and make rendering better, right?

3:10

Like, don't re-render this thing. But

3:12

it goes much further than that. So

3:14

it goes into... I

3:17

was talking to someone on the forcel team

3:19

that works on the forcel website recently. I

3:21

was showing in the React compiler side

3:24

to side to what, if you don't have it enabled.

3:27

It was like, I thought this is

3:29

always how React worked already. So why are you

3:31

showing me this new thing? So

3:35

another way that I look at it is, it

3:38

makes the assumptions that you had around how

3:40

React renders a bit more the

3:44

reality with the compiler. Because you don't have

3:46

to think about, where do I

3:48

add memo? Where do I add use callback? Where do

3:50

I make sure that things don't re-render? And

3:53

instead, you can just write my,

3:55

like, project logic and combine

3:58

it and configure it. Does

4:00

this thing need to be memoized? Does

4:05

it not need to be memoized? Because

4:08

the other side of things, early optimizations, at

4:11

some point you get so into React that you get over this.

4:15

It's like this meme where you go

4:17

to peak and then back to

4:19

not memoizing anything. At some point you're like, I know React so

4:21

well. I'm

4:25

going to memoize everything. I

4:27

don't want anything to change between renders. That's not

4:29

always the best way to do it in the

4:32

end. The

4:34

React compiler can just take your

4:36

original source code, it can optimize

4:38

it in various ways by memoizing more

4:41

bits. It's not just

4:43

the state VMIs or specific

4:45

derived state as well, but

4:47

it's more like it can memoize

4:50

your JSX as well, for example. In

4:52

some cases when some input values change,

4:55

only a part of your JSX tree needs

4:57

to change. It

4:59

can automatically make sure that those

5:01

cases are also not re-rendering in

5:03

this case. That's one

5:05

question I had, and I haven't been able to

5:07

figure this out. When

5:10

people have context, you

5:12

put the context in a provider, and

5:15

when the values in context change, a

5:18

higher subtree of context will re-render

5:21

itself. That's always been the

5:23

thing, it's like, don't put context too high. Then

5:26

I tell myself, I kind of want it high,

5:29

because I just want my data where I want it,

5:32

and I want it to figure it out

5:34

for me. Is that something that the React

5:36

compiler is going to fix for us? The

5:42

lesser-known one is that, so it doesn't

5:45

fix that, I think. I'm

5:47

not 100% familiar with this, so don't pay

5:49

me down a little bit. I don't think

5:51

it fixes the context one, but

5:53

it does fix the other case, which is like prop

5:55

drilling. When you're

5:57

writing an app that is like a... in

8:00

front of you right now. Usually

8:05

you would never do yourself, or

8:10

it's like, peak, I'm going to memorize everything. When

8:15

the React compiler goes stable, once

8:20

it goes stable, you wouldn't have to think about this anymore.

8:25

You're like, by the way, this is things that

8:27

I could have done myself, but I'm actually not

8:29

doing. One example

8:31

is you define a variable, const

8:34

a is 10, like a string or

8:36

integer that you put in. That's

8:39

just constant. It

8:42

can actually reason about that and move

8:44

it into the place where it's used

8:46

instead of having it in the function

8:48

scope where it

8:50

is completely reinstantiated because of

8:52

the re-rendering. That's

8:54

one thing that I think a lot of

8:57

people don't realize is that if you

8:59

need a little function inside of your

9:01

component because you handle submit or something

9:03

like that, if you define

9:05

that function inside of your component, which a lot

9:08

of people want to do because you have access

9:10

to your state and everything else there and you

9:13

don't have to pass it all in,

9:15

then every single time that component is

9:17

re-rendered, then that function is reinstantiated. Unless

9:19

you're using a use callback and it

9:21

gets really complex really quickly

9:23

and I'm really glad that this

9:25

will do that tricky stuff for

9:28

us. Yeah. Let's

9:31

take it back to Next.js for a second too. Given

9:34

that you said this stuff's all in preview

9:36

and it's coming from the React team, does

9:39

Next need any modifications to

9:41

take advantage of this stuff once

9:43

it is launched or are people

9:45

going to be able to use

9:48

this with whatever compatible Next.js version

9:51

or the React version when it's fully released? Yeah,

9:55

for sure. It's

9:57

using some APS that are in React that are also

9:59

not available. available in React 18, for example. So you'll

10:02

have to use React 19. So today

10:04

you have to install React 19 RC. If

10:07

you're using Uprighter, you don't have to install React

10:09

itself because we ship the version of React that

10:11

you need. But

10:13

in practice, you need React 19 because

10:16

of specific APIs. There is a polyfill

10:18

for it, but journey speaking, probably

10:20

don't want to use it. Just use

10:22

the latest React instead. And

10:26

then the thing you have to do in Next

10:29

is using a bevel transform today.

10:33

The important thing to notice is it's not

10:35

a bevel transform in the sense that

10:37

you would usually think of, I'm going

10:39

to take my input and give some

10:41

output. It does generate some

10:43

output, but in between, there's a different

10:45

compiler that has a

10:47

reasoning about bevel AST, but it could

10:49

also support SVC in the future or

10:52

any other parsing

10:54

and AST transform, basically.

10:57

So on that side, it means that we have

10:59

to add bevel because we've been on

11:01

this journey to move away from bevel

11:04

for compilation for

11:06

Next.js using SVC instead,

11:08

which is significantly more

11:10

performant for individual file compiles.

11:14

But now we have to add back bevel,

11:16

for this case at least, until they

11:19

start an industry ride or something like that.

11:21

That has already been experimented with by the

11:23

team as well, by the React team. In

11:25

practice, if you're using Next.js, all you have

11:27

to do is upgrade to the React 15,

11:30

the Next.js 15 RC, and

11:33

upgrade to React 19, which

11:36

is something that they'll just tell you

11:38

to upgrade because we also depend on

11:40

that. And then you have to enable

11:42

experimental React Compiler through and

11:45

install the compiler because the compiler right now is in

11:47

beta, so we want to make sure that you can

11:49

upgrade it yourself so you can get the latest improvements

11:51

to it whatever you want instead

11:53

of being in lockstep with Next.js itself. That

11:56

doesn't sound too painful. Yeah.

11:59

Awesome. Let's talk about React

12:01

server components. I'm sure that you're

12:04

probably one of the top people in the

12:06

world who's, who's heard so much of the

12:08

feedback, good and bad from, uh, react

12:11

server component world. And also, I think

12:13

there's like a lot of confusion around

12:15

and around what it is. So are

12:17

you able to give us a quick,

12:20

your idea of what react server

12:22

components is and, and how

12:24

we should be approaching our applications? Yeah,

12:27

it's a, it's definitely a hard one. It's

12:30

been a hard one to explain to people,

12:32

uh, as you've probably seen, uh, online, so

12:34

released, uh, server components and next chairs like

12:36

one and a half years ago or like

12:39

slightly over one year ago now, um, one

12:42

half years ago for like the, the initial like beta

12:44

release of it. Um, we could try

12:46

it out for the first time. I really liked react

12:48

server components are like, like, like

12:50

it's sad in the name, but like you

12:53

render react components on the server slightly different

12:55

from what you did before. So like next

12:57

year, uh, since the very first version had

12:59

a service at rendering service

13:02

at rendering is like taking react components, generating

13:04

HTML, react server components is

13:06

more of a like

13:08

step before that. That basically replaces everything

13:10

that you did with get service or

13:12

props, get static props. Um, and then

13:15

like, it's able to render react components

13:17

as part of that. Um,

13:19

there's a much better and like deeper

13:22

and like more high level explanation of

13:24

this in a dense talk at react.com

13:26

would definitely recommend looking at that. Uh,

13:29

and that, that one talks about like react for two

13:31

computers, which is like, I'm running

13:33

react on two computers. Like

13:35

one, one computer is, uh, the, like the

13:37

server basically. And it, like it doesn't start

13:39

out there, but like, that's where I know

13:41

what's spoiled the entire talk, but it's like,

13:44

you basically end up with like, you

13:46

have a, like one computer is your server. The

13:48

other computer is, uh, the browser, and you can

13:51

move logic between them in like

13:53

whatever way you want because

13:55

everything is one rendering model. Uh, so you're

13:57

still using react. You use like, familiar

14:00

with, the only

14:02

difference is that NaRIAQ has this primitive that

14:04

allows us to render on the server only,

14:06

which is something that we couldn't do before.

14:09

That unlocks some other benefits. One of them

14:11

is that you can now do data fetching

14:13

on the server, where you don't need special

14:17

framework APIs. We

14:19

initially coined the get initial props pattern, where

14:21

you can do data fetching on the server

14:23

and on the client. Then

14:25

later on edit, get service at get static

14:28

props, get service at props, get static

14:30

props. Get service at

14:32

props was just a way to say,

14:34

before my React rendering starts, I'm going to

14:37

get, the framework is going

14:39

to call this function. Then I

14:41

as the application developer can write some

14:43

logic that gets data from anywhere. It

14:45

could be a database or an

14:48

API or anything like that. Then we

14:50

pass those props into the component. Now

14:54

with server components, that step is basically

14:56

replaced with a full

14:58

React render. That means I

15:01

can write components, those components can do

15:04

data fetching, and they can render other

15:06

components as well as interactive

15:10

components that are the ones that you wrote

15:12

before. If you're familiar

15:14

with React, it's just

15:16

an additive feature basically on

15:18

top of everything that you already

15:20

knew that allows you to do

15:23

even more than we would ever have

15:25

hoped for when we started Next.js

15:27

for example. I

15:29

can now do data fetching in my

15:31

components or deeper into the React tree.

15:34

I could share libraries

15:37

that do data fetching and provide

15:40

components for that. It

15:43

is fully portable in the React ecosystem

15:45

as well, once more frameworks

15:47

start adopting this. One

15:50

example of that is that Remix is looking

15:52

into server components, the Red Boot folks are

15:54

looking into server components, and at that point

15:57

you basically have a

15:59

React component you can write. right,

16:01

that is encapsulating both like client side behavior

16:03

as well as server side behavior. And

16:06

like one example of that is I can

16:09

build a like MySQL

16:12

admin type React component. And

16:15

that's portable between all frameworks that

16:17

use React server components. And

16:19

it can pass in like props there.

16:21

And they can be interactive as well,

16:23

right? You can add like interactions using

16:26

server actions or things like that as

16:28

well. Yeah, it's really exciting to me

16:30

that we'll now be

16:32

able to ship components that define how does

16:34

it work on the client, how does it

16:36

get its data, and how does it render

16:38

on the server, all inside

16:40

of an encapsulated component. Because

16:43

one of the things that people, like

16:46

people who build like websites for clients, they're

16:49

still saying, I want like the WordPress

16:51

plugin experience, right? Yeah, right. And that

16:53

has always been really tricky to like

16:55

move to the React world.

16:57

But now with this idea of like,

17:00

yeah, you can NPM install something

17:02

and its batteries included for all

17:04

of that, maybe pass in tokens or

17:07

auth or something like that, it's pretty

17:09

exciting to me. Yeah,

17:11

it's really cool to see. Obviously,

17:14

like when we just released it, there was like

17:16

a lot of pushback, like, oh,

17:18

things are getting more complicated. Why

17:21

do I need to know about this use client thing?

17:23

Or like what are client components even? Why is this

17:25

a new thing? And like those were not even like

17:27

the new thing, right? So they were like the thing

17:30

that you already had. Just give it

17:32

a name, basically, right? And then server components were

17:34

the fully new thing where you had to be

17:36

like, I want to use

17:38

state, right? Like, let me call you state

17:40

so that I can like click

17:42

this button and then like something is like

17:45

shown or something like that. But

17:47

you can't do that on the server. Because like obviously

17:49

the server doesn't have this interaction model of being able

17:51

to like render and

17:53

then like re-render at some point. As

17:56

part of like running on the server.

17:58

So there's like new constraints. on

18:00

that environment. Especially

18:05

confusing to people coming from, I'm

18:10

only using clients that react and then moving

18:12

to, I

18:15

can only do certain things on the server type thing. One

18:20

of the cool things that we're seeing now at this point is

18:25

that I provide RSE-enabled features.

18:30

One great example is Payload CMS

18:32

is building their entire editor as

18:35

React Server components with server actions and all

18:37

that. What

18:40

they allow you to do is they

18:42

allow you to bring the entire

18:44

CMS as a React component. Those

18:52

can adjust behavior in the CMS

18:54

itself. You can build override

18:57

particular fields in the CMS, which is

18:59

really cool to see as well. So

19:05

many like Sanity is doing something like

19:07

that as

19:09

well. We're finally at the stage where people

19:11

are coming around to it and

19:15

they're seeing, okay, this thing actually does make sense for

19:17

my case. But

19:20

maybe only the clients and

19:22

navigation optimizations or specific features

19:25

of React that are enabled by this, transitions

19:28

and things like that. It

19:30

definitely feels like the ReactConf, if

19:33

you're into React, I highly recommend watching

19:36

literally all the talks in the entire

19:38

livestream, which is eight hours long. All

19:42

of them are super high quality. I did it myself.

19:44

Don't do it in one sitting, I would

19:46

say. I'm not speaking.

19:51

The talk that Dan gave clarified server components click

19:53

for me now. It

19:55

was the general thing I heard from people. Similarly,

19:58

you're seeing other... Like,

20:00

uh, like explanations of like, how is this

20:03

like making sense to me now in, in like my

20:05

particular case. So even if you're building like an SPA,

20:07

you can still leverage like suspense

20:10

and transitions and like async transitions,

20:12

for example, to make

20:14

it easier to like schedule work and things like that. What

20:17

does that look like for somebody who

20:19

has built an entire application that is

20:22

maybe a next JS and it's

20:25

client client hydrated, right? And they say,

20:27

okay, well now I want to start

20:30

opting in to, to server components. Um,

20:32

I think that's where a lot of the frustration from

20:34

people go because they go, yeah, oh yeah, I'm going

20:37

to start using server components and then you import something

20:39

that has a hook in it or

20:41

is met for the client and you get all these,

20:43

these errors and people get really frustrated with it. Right.

20:46

What, what's the path? Like, what do you recommend

20:48

for somebody when they're moving over? Yeah.

20:52

So it's, it's kind of like, um, the

20:55

misconception is like where you start migrating, so like

20:57

the, the, the, where you start migrating is like,

20:59

usually people are like, I'm going to use this

21:01

for this small component on the page. That is

21:03

like, like a button that

21:05

doesn't need interactivity, right? Or something like that.

21:08

However, the, um, the entire model is

21:10

built on the other way around,

21:12

like you're introducing server components at a place where it

21:14

gets service. I props walls. So that's like before

21:17

the actual like, like client

21:19

components rendering. What that means

21:22

is that if you want to start migrating

21:24

the first place where you start is not

21:26

so much at this

21:28

like granular level per se. It's

21:30

more the outer layer of the

21:32

app. So when you start migrating,

21:34

the first thing that you do, um, and there's

21:37

many ways to do this, but like the first thing

21:39

that you usually do is like you go into like

21:41

page.dzax or page.js. Uh,

21:44

usually people like TypeScript nowadays, but like you

21:46

can still use JavaScript as well if you

21:48

want. Um, the first

21:51

thing you do is like you, you add, uh,

21:53

because you already have this page that's ex or

21:55

like maybe you're using pages, right? Or ends like

21:57

index that you asked or something like that. Yeah.

21:59

So you. create this page with TSX and you

22:01

don't add use client there. What

22:04

you do instead is you write a component and

22:06

import another component and in that

22:08

component you add use client. That's

22:11

what that means is that now the outer

22:13

layer is a server component and

22:16

the inner component you're rendering in that server

22:18

component is a client component. Okay,

22:21

so basically you're taking your page and

22:23

you're saying this page is server rendered.

22:25

Now I'm going to opt in

22:28

everything to client right? You say use client that's

22:30

kind of I was moving my own website over

22:32

to it and I was like alright I just

22:34

need it to work. I made

22:36

everything use client and then

22:38

you can keep going on that but I started

22:41

chipping away at it. Yeah, yeah. That's

22:43

a great when you're migrating anything

22:45

to get the versions up

22:47

and then get the site at least back to

22:49

where it was before opting into the new stuff

22:52

I think is always a good strategy. For me

22:54

it was like a mental hurdle where I was

22:56

like no I don't want it. I want it

22:58

all to be server rendered. Then I was like

23:00

telling myself Wes the whole

23:02

freaking website was client rendered previously.

23:05

Yeah, it's okay to go back

23:07

to the whole website being client

23:09

rendered incrementally. You opt into to

23:12

each of them. So like once

23:14

you're at a page server rendered then what do

23:16

you how do you handle that page? So

23:19

yeah like migration story you

23:21

already have a website like syntax for

23:24

example which was built on on the

23:26

next before you

23:28

basically just take that that like page you had in

23:30

the pages writer and usually that

23:32

one had to get static props or get service or

23:34

props. So the way to think about is that the

23:36

component you're adding as like page that these acts that

23:39

one is the one that is doing to get service

23:41

or props or get static props that you previously did.

23:44

So instead of like having the specific like

23:46

export function get service or props what

23:49

you do now is you move all that logic

23:51

into this async server component that

23:53

is the page itself. So you

23:55

move all that logic down and then you

23:57

create a separate component that is just the

23:59

theme that was rendering before. And

24:02

that separate component, you add useClient, and

24:04

you pass all the props in, same way that

24:06

getServiceProps passes them in. That

24:09

we do in like Nexus internals, basically, right?

24:12

Which is just like you pass the props. Literally,

24:14

you just add a props object there. You spread

24:16

on to the item. Then

24:19

the next step there is, there's many

24:22

ways to do this. But you can say maybe

24:25

that first component that is using the

24:27

props is also not interactive. It doesn't

24:29

have useClient, or it doesn't need useClient

24:31

because it doesn't have useState. It doesn't

24:34

use effects or anything like that. So

24:36

what you do at that point is you say, I

24:39

move it done one more level. So

24:41

now we're down to maybe

24:43

if that page was like the shell

24:45

of the page, like header, the content,

24:48

and then the footer, maybe

24:50

only the content

24:52

doesn't need it, but the header and

24:55

the footer do need some interactivity that

24:57

is like useState or useEffect. So

25:00

what you do at that point is you just move the

25:02

useClient deeper and deeper until the point

25:04

where you're like, it doesn't really make sense anymore to

25:06

do this. And then for

25:09

the first iteration of it, you're done at that

25:11

point. At least

25:14

that's my opinion on migrating these

25:16

Nexus apps. The

25:18

misconception that people have is my Nexus app in

25:20

PageSrater is bad. I need to move to AppRider

25:22

to then move everything to the server. You

25:25

don't have to do that. You can just use

25:27

client components. Client components are fine. I

25:31

think when

25:33

we released server components in Next.js, we

25:36

talked so much about what server components can do. It

25:40

was lost that client components are fine and

25:42

they're part of the same model, and you

25:44

should be using them still. There's no reason

25:46

that the interactivity of clicking

25:48

buttons or opening menus or popovers or

25:50

anything like that is

25:52

server-side behavior. You

25:55

can still use all the features of React. Client

25:58

components are totally fine. Basically,

26:00

right. So at that point, you're done

26:02

for now. And then what you can do from that

26:04

point on is like you can say, maybe

26:08

some of the things that are in my header are actually

26:11

things that can render on the server and they need data from

26:13

the server. So what you

26:15

do initially is you're passing like maybe

26:18

you're fetching all the data for the page, which is what

26:20

you did in the get service with props, get static props.

26:22

You're passing all the data from the page, like done

26:25

into these like other components,

26:27

right? So you're passing into

26:29

your header component, hey, this

26:32

is the data for the header, for example. So

26:35

what you can do at that point is you can move the data

26:38

fetching further down or like

26:40

if that is at all possible, doesn't have to be

26:42

that way, right? You can also say, I'm still going

26:44

to do all my data fetching at the top. But

26:47

you do get some benefits from moving them down

26:50

at that stage. So at that stage,

26:52

you can say, I'm going

26:54

to introduce suspense boundaries to show more like loading

26:56

states in my page, for example, my content can

26:58

come in later than the header, for example, that

27:00

kind of thing. So

27:02

what you can do at that point is you

27:04

can introduce suspense boundaries, like slightly deeper in the

27:06

tree, while the rest is still

27:08

a client components. Then you

27:11

already get a slightly better experience because you can

27:13

get the header, the footer, but then like the

27:15

content has a loading stage, like a skeleton or

27:17

like some kind of like spinner and anything you

27:20

want really, you can provide your own

27:22

loading stage there. But at that

27:24

point, you've already improved the

27:26

experience of your app. It streams in like

27:29

faster. You get like faster times first byte,

27:31

slightly better core web titles, that kind of

27:33

thing. And then you can

27:36

say, maybe I need to start moving some

27:39

of my other like parts of the header, for

27:41

example, to be partially

27:43

server components, partially client components.

27:46

So one of the very interesting things

27:48

is that it's a one way street.

27:50

It's like a door, which

27:53

is like a hole to the other side

27:55

of the, to the

27:57

other machine, to the other computer, which is

27:59

the client. So now

28:01

you can say in my server components, I

28:05

can pass data to my client components. I

28:07

can pass data to the browser, for example,

28:09

even though there's still like rendered HTML on

28:11

the server. I can just like

28:13

pause these props that I pre- it's similar to

28:15

what Get Server Props did, right? So you just

28:17

like do some data fetching and you pass it

28:19

to the browser as well. And

28:21

if you ever looked at the connections app, you

28:24

would see like underscore underscore next data. And

28:27

that would have like a large blob of like all your data

28:29

for Get Server Props. Server components are

28:31

client components. Yeah, sorry. I want to talk about that

28:33

for just a little bit because I think that's really

28:35

neat. For the longest time,

28:37

I was like, I really wish Next.js

28:40

would come out with like a state

28:42

management or like a data fetching library

28:44

or some opinionated way to

28:46

fetch data and pass it to the client.

28:49

Yeah. And for

28:52

the longest time, I was like, can they please do this? And

28:54

then server components came

28:56

out and Next.js had this

28:58

like revalidate tag, revalidate path,

29:01

cache API. And I thought

29:03

like, I'm not sure

29:05

I need that anymore because you can

29:07

make a server component fetch the data

29:09

and you can pass it to the

29:11

client component via props. And

29:13

you can clear that data with

29:15

revalidate tag. And I

29:18

went from wanting this like Redux

29:20

type store on the

29:22

server or on the client server to

29:24

it's just a fetch request with props.

29:27

Yeah. Was that the... Do you see

29:29

a lot of people saying that? Yeah,

29:31

I think that started with the get

29:33

static props, get service or props already

29:35

a bit. There was like a lot

29:37

of like cases that

29:39

you can model in this way. The only thing that

29:42

was missing was like a primitive for what

29:44

do I do when I do interactions. So like

29:46

interactions could be like client

29:48

set interactions like state and like effects and

29:50

like on click and kind of thing. Or

29:53

it could be interactions that involve

29:55

the server. So like things that are like submitting

29:57

a form or things like that. on

44:01

Express middleware. And I'm

44:03

thinking to myself, all right, I'm going to

44:05

move off Express eventually. And

44:08

what happens is I'll have a middleware

44:10

where I'll attach a user ID or I'll

44:13

attach a country, and then I'll move

44:15

on to the actual handler. And then

44:17

you assume that data is in the request.

44:19

So I moved a lot of that

44:21

out of sticking it into the request and

44:23

then pulling it out. I moved that

44:25

into the async local storage API because then

44:27

it's just as long as it's in

44:29

the call stack, right, it's available to

44:31

you. And Next.js uses that as well for

44:34

what, cookies and headers? You simply just

44:36

call? Yeah. What's the API? Yeah,

44:39

it's literally cookies and headers. So you

44:41

call cookies or you call headers and

44:43

you got a cookie store, header store,

44:45

back header object. React

44:47

uses it for the cache

44:49

API as well, like the new, like the

44:52

one that you can call to

44:54

dedupe in the same rendering on

44:56

the server. I think it's like

44:58

part of that actually. The React

45:01

cache doesn't work in

45:04

the same way across

45:06

this rendering basically. So

45:09

that might be one of the buckers. Because otherwise, if

45:12

you do data fetching and you want to dedupe it

45:14

in some way, you just can't because it's just not

45:16

tracking that in this way. So

45:19

maybe something like that. Yeah, OK. We

45:23

got 10 minutes left. I got a lot I want to

45:25

ask you about here. That's what I was looking through here.

45:27

Our questions were like 10% of

45:29

the way through the ones that we had

45:31

written down before. I think if we could touch

45:33

really quickly on Turbo Pack, like what it

45:35

is and what problems it's going

45:37

to solve, I think that would be probably useful.

45:40

And if we want to have an entire

45:42

show on Turbo Pack at some point, I'm

45:45

sure we could open that up as well.

45:47

So Turbo Pack obviously is the, or maybe

45:49

not obviously, it's the rewritten web

45:51

pack in Rust or it's the

45:53

succession to web pack. And

45:57

Next.js has been running on web.

46:00

for very long and what problems

46:03

have you hit so

46:06

that you need to build Turbo Pack? Yeah,

46:09

it's definitely a long journey on

46:11

a web pack. When

46:14

we released Next.js, it was initially built on

46:16

web pack and this is quite

46:18

some time ago, it's 2016. We've

46:22

been around, as they say, in

46:24

the framework lens, like we survived for a

46:26

long time. It's similar to the

46:28

rest of the industry. Basically what

46:31

is happening over these seven years

46:33

is that people start building larger

46:36

and larger and larger apps on

46:38

these frameworks. So it's not just

46:40

on Next.js, it's also on Next

46:42

and other frameworks. So

46:44

what we see is that people just end up pulling in

46:47

more modules, more NPM packages,

46:49

more larger UI libraries. So

46:53

like UI libraries, you might think of like, they're

46:57

probably shipping like 100 components, right? But if you

46:59

look at some of the newer libraries,

47:02

like I'm not

47:04

going to destroy anyone here actually, like

47:06

some of the new libraries are shipping like 10,000 re-exports,

47:09

right? Like they're shipping like 10,000

47:11

different components that you can import.

47:14

But in order to process those, we need

47:16

to compile all those 10,000 modules and then

47:18

say which one is actually used and like

47:20

skip, like if you can't really skip over

47:22

a bunch of these. And

47:25

sometimes you do like import star as like

47:27

some library name and that means we have to

47:29

compile all of them, right? Like that kind of

47:31

thing. So as

47:33

a complexity of like JavaScript applications

47:36

keeps growing, we're basically like hitting

47:38

these limits of Webpack

47:40

itself, of like some of the newer

47:42

vendors even. So

47:45

what we started out with is like, we were

47:47

basically evaluating like, does it even make sense to

47:49

keep like running a Next.js or

47:51

like running Next.js on Webpack or should

47:53

we use some of the like

47:56

newer vendors that came out or anything like that. And

47:59

then, when we looked at the complexity

48:01

of the apps that we already

48:03

get with Nexus today, as well as

48:06

all the complexity of extra

48:08

bundling for server components, client

48:11

components, multiple passes, maybe you

48:13

want to deploy on the

48:15

Edge or Node.js, and then

48:17

there's just a complexity in

48:19

the amount of modules that

48:21

get processed. One example of

48:23

that is if you have

48:25

a client component, like

48:28

as you probably know, and maybe not even knows, client

48:31

components render on the server as well to

48:33

render HTML to basically speed up the initial

48:35

render. In

48:38

order to get there, we need to take your

48:40

module, and your module is importing,

48:43

say, a large icon library that is the 10,000

48:45

React support, for example.

48:47

Now we need to process those 10,000 modules for

48:49

the server as well as for the client

48:52

because they're in different conditions. They

48:54

get different optimizations, they need to

48:58

maybe those, for the browser, need to

49:00

be ES5, for instance, the server can

49:02

be whatever, like Node.js version you're running,

49:04

that kind of thing. That

49:06

means we have to process all of them pretty

49:09

quickly. What

49:11

it means to practice it, instead of 10,000 modules, you're processing 20,000

49:14

modules. That stacks up really quickly

49:17

as you get more

49:19

and more modules into your client components, into your server

49:21

components, that kind of thing. We

49:23

really have to build a solution for how

49:26

can I optimize these very

49:29

large graphs and make sure that everything is

49:31

processed in a way that is reliable

49:33

as well? Because for Webpack,

49:36

Webpack doesn't support running both

49:38

server and client compilation in the same compiler.

49:41

What we do for Webpack is we run

49:43

three compilers. We

49:45

run one for the server, one for

49:47

the client, and one for Edge. Edge

49:49

is the special target

49:51

where you get a slightly more constrained

49:54

environment. In order to coordinate

49:56

that, we have

49:58

to manually coordinate. You start

50:00

now, you start then type thing. This

50:02

one is done. Now we need to trigger this other one.

50:05

And we just knew that that wasn't as reliable as we

50:07

wanted it to be. So

50:09

eventually, we started building TurboPack,

50:12

or what turned into TurboPack, which

50:15

is a single. The

50:17

idea was we created a single module graph that

50:20

can span the server, client, server components,

50:22

client components, edge, whatever you run into.

50:25

And it can just process all of these

50:27

modules in parallel,

50:30

because Webpack is limited to single core

50:32

right now. You can

50:34

add some parallelization, but it's not super.

50:37

It doesn't speed up things that much. We

50:41

leverage all the latest compiler

50:43

technology or transform technology, like

50:45

SLVC. We

50:48

implement caching from the start. One

50:51

of the issues that Webpack had from

50:53

the start was that it was

50:56

a research project by Tobias. The

50:59

original story of Webpack is pretty interesting as

51:01

well. It turned into this thing

51:03

that everyone used. From the

51:05

start, it wasn't built to be this thing that everyone used.

51:08

So over time, they had to optimize

51:10

a lot, add more caches, add hot

51:12

caches into the system, add disk

51:15

caching on top of it, and things like that. And

51:18

what we did for TurboPack is we started out with the

51:21

caching layer. We need to

51:23

have a task runner caching layer

51:25

that is as solid as

51:27

it can be, so that you basically get

51:30

reliability from the start

51:32

across parallelizing across many

51:34

CPUs, caching for

51:36

disk, that kind of thing. And

51:39

then we can build any tooling

51:41

we want on top of that. So we basically

51:43

built a library called TurboEngine. TurboEngine

51:46

is the thing that is powering

51:49

all of TurboPack. And

51:52

potentially in the future, also part of TurboRepo,

51:55

because they recently rewrote everything in Rust.

52:00

works is that anything she writes

52:03

in Rust, you can basically

52:05

annotate with this function directive from

52:07

Turbo Engine. And that

52:09

makes it cached by default automatically. It

52:13

knows when to rerun when you do disk

52:15

IO, for example. And it just automatically works

52:17

out of the box with that. What

52:20

you get with having this caching layer is

52:22

that now, anytime you make a change, we

52:24

can quickly recompute what thing changed and

52:28

what thing needs to be recomputed. And we

52:30

only recompute that narrow part of the graph. So

52:33

that means that any time you make an

52:35

initial compile, it still compiles all your

52:38

modules, right? But then when

52:40

you make a change, it can just recompile

52:42

only to CSS. So it can recompile only

52:44

the tiny part of the JavaScript that needs

52:46

to be recompiled and then apply it on

52:48

the server, apply it

52:50

on the client through Fos Refresh or

52:52

anything like that. One

52:54

of the goals was

52:57

also to bring Fos

52:59

Refresh down to sub 100 milliseconds

53:01

or so. Oh, yeah. Oh, that's

53:03

awesome. For like pretty

53:06

much all changes, except for server components, because

53:08

server components also need to render on the

53:10

server. So we re-render the entire page. In

53:12

that case, if you're

53:14

changing client components, it's near instant, basically,

53:16

right? The problem we had with Webpack

53:18

was that it's not near instant when

53:20

you have these 20,000 modules or

53:23

30,000 modules. Because

53:25

that graph of changes

53:27

is massive in the Webpack case.

53:30

So it would take one,

53:33

two seconds before you see anything on the

53:36

screen. And if you were unlucky, you would

53:38

get a much larger recompile, and it would

53:40

take much longer than that, even. So

53:43

that was one of them. And then the

53:45

other is that most of the things that

53:47

people are complaining about are not recompiled times,

53:49

actually. It's the initial compile. So

53:52

it's just like, I boot up the server. I

53:54

go to a page. How long does it take

53:56

me to show that page? And we're combining those

53:58

on demand, right? So that means. And

54:01

we're basically shifting the rug from you boot up the server

54:03

and then you wait

54:05

for five minutes, which is what you

54:07

would get with some of the initial

54:10

versions of confiders that were

54:12

built on top of Webpack, for example. Instead,

54:14

what we do is we only start

54:17

compiling where you actually request a page and

54:19

we only compile the stuff for that page.

54:21

For that, the parallelization

54:23

is a big optimization,

54:26

as well as having persistent caching. Yeah.

54:28

For parallelization, we have kneel down and that

54:30

works. What is really interesting is that for

54:33

the for cell website, what we saw is

54:35

that on some of the slower pages,

54:38

Webpack with a

54:40

cache, like this caching, would actually be 10%

54:42

slower than Torupak

54:44

doing everything from scratch. So

54:48

that was like one of the interesting wins

54:51

that we had. And comparing it to

54:54

running it against cold Webpack would

54:56

be even better, obviously. But

55:01

that was one of the things that I was really interested to

55:03

see. And this is without us having persistent

55:05

caching in Torupak yet. So that's what we're

55:07

working on right now, to have persistent

55:10

caching so that if Scott starts to work

55:12

on the syntax website, he

55:14

makes some changes. He might not

55:16

be working on it every day. So

55:19

you make some changes, you push

55:21

them to production, and

55:24

then you wind

55:26

on the server. So you control C and you

55:28

just go ahead with your day. And

55:30

the next day you come back and you start up

55:32

again. You have to wait this initial compile time again

55:34

because there's no discussion yet. Now

55:36

when we have this caching, you can just go

55:38

from the point where you left off. So

55:41

the last time you run the

55:43

compiler. And now you might

55:45

be thinking, oh, but this might make sense for

55:47

builds as well. Because my builds are in the

55:49

cloud. And maybe they can

55:51

store all that and then restore it and

55:53

make my builds almost instant. Because you just

55:56

told me about this smaller graph

55:58

that can just recompile changes. sick

58:01

pics and shameless plugs. I'm not sure if

58:03

you came prepared with those. I

58:06

think I have like one kind of

58:08

into a sci-fi series. And

58:11

if you're into sci-fi series, I highly recommend

58:13

Apple TV Plus, which

58:16

is like, for some reason,

58:18

they keep putting out more sci-fi series.

58:21

We don't have particular like here in

58:23

the Netherlands, because I'm not from the

58:26

US, like they don't have like specific

58:28

like sci-fi channels like the sci-fi channel

58:30

itself, the kind of thing. So

58:32

like a lot of that is like on Apple

58:34

TV. So I don't

58:36

think I realized how many different sci-fi

58:38

shows they had, because I guess is

58:41

silo considered sci-fi or foundation

58:43

for all of mankind? It's like

58:45

wow. Yeah, it's it's pretty crazy.

58:47

Like overall, I had never thought

58:49

of like after before and like

58:52

I opened it once accidentally, I

58:54

was like, huh, this is interesting.

58:56

There seems to be like quite

58:58

interesting like series

59:00

on there. So like silo is pretty good. That's

59:03

like it's all I think they made

59:05

a lot of deals with like book authors as well.

59:07

Yeah, just based on the books a lot. They're

59:11

now also getting like into the like

59:13

documentary about controversial thing

59:15

that happened like like

59:19

the Hollywood Conqueen started watching recently, which

59:21

is by the

59:23

by the creators of the fire

59:25

festival. Oh, really? documentary and things

59:27

like that. Yeah, those are

59:30

there's some pretty good stuff there. So if

59:32

you're interested in in sci-fi, foundation is really

59:34

good as well. It's definitely like they keep

59:36

bringing out like more of those. Not

59:39

sure. Like there must be someone like

59:41

uploads cute. It's like I love sci-fi.

59:43

Yeah, I bet. Yeah. I

59:45

wonder if they have serious data on

59:47

on podcast because I know

59:50

that Hollywood Conqueen podcast is really,

59:52

really hit. So I wonder if they saw that and were like, oh, this

59:54

would be a good doc. You. Huh.

59:57

Cool. Awesome. And shameless plugs. Well, would you like.

59:59

to plug to our audience. Vape Toropec

1:00:02

RC, or like the, yeah, the Toropec RC.

1:00:04

So we have the Nexus 15 RC, which

1:00:07

is like new features using

1:00:09

React 19, some caching

1:00:11

improvements as well. If you didn't like

1:00:14

the previous caching, we

1:00:16

disabled most of it. And

1:00:18

it's all obtained now. We're

1:00:20

definitely listening to feedback there. It

1:00:24

was just too complicated from the start. We

1:00:26

tried to make it very similar to Pages

1:00:28

Rider with automatic

1:00:31

static generation. But

1:00:33

it became complicated in the cases where you

1:00:35

do want to be dynamic. So there are

1:00:37

just better defaults now. You

1:00:39

can opt into more static behavior once

1:00:41

you want to optimize more, basically. It's

1:00:45

purely based on feedback and

1:00:48

just giving people the thing that they

1:00:50

want to build better websites. Besides that,

1:00:52

yeah, Toropec is an RC for development

1:00:54

now. So that means please

1:00:57

try it out. If you have any issue,

1:00:59

like literally any issue, if it's slow, anything

1:01:02

like that, tweet at me or open

1:01:04

an issue on GitHub. We're actively working

1:01:06

on it. We have like

1:01:09

30 open issues left

1:01:11

so far before like development

1:01:13

is fully done. And then

1:01:15

we'll shift to working

1:01:17

on builds as well and bring

1:01:19

you that persistent caching and FTP

1:01:22

builds and things like that. I'm excited

1:01:24

for that. I have

1:01:26

one more shameless plug as well, which

1:01:28

you'll like. There is. It's

1:01:32

about Sentry, actually. Oh, OK. Let's hear it. I'm

1:01:34

not sure if you know. I

1:01:36

think its name is Luca. So

1:01:38

Luca on the Sentry Nexus

1:01:40

SDK team has

1:01:43

been doing some contributions to Next to basically

1:01:45

allow Sentry to reason about server side errors

1:01:50

that are then sent to the client with

1:01:52

a special digest. I'm not sure if you've

1:01:54

seen that in Next. We need

1:01:56

to hide all the data because we don't

1:01:59

want you an error, you don't want

1:02:01

that to end up in the client, because in some guys

1:02:03

it contains anything that could be

1:02:05

secret. But now

1:02:07

Sentry can actually reason about that

1:02:10

particular error that happened on the server, as

1:02:12

well as the thing that happened on the

1:02:14

client, so the thing you saw on the

1:02:16

client. So it can actually mark

1:02:18

the session as like, this is the error that

1:02:20

was related to that particular digest. So you can

1:02:22

search for the digest in the UI as well,

1:02:24

which is pretty neat. Oh,

1:02:27

that's awesome. Yeah, we'll link

1:02:29

that up as well. Sentry

1:02:31

is doing a lot for that. I

1:02:34

know you guys did some work on the

1:02:36

hydration stuff. Sentry has been constantly working

1:02:38

on getting better hydration issues. And

1:02:42

what is the source maps? It's one thing Sentry

1:02:44

is spending a ton of time on pushing

1:02:47

forward in JavaScript in general. So

1:02:50

love to see it. Awesome. Well,

1:02:52

thank you so much for all of your time for coming

1:02:55

on. Thank you so much for Next.js, working

1:02:57

on it, as well as coming on today to

1:02:59

school us on all of the stuff that's going

1:03:01

on with React and Next.js. Appreciate it. Thanks

1:03:03

for having me. Thanks, Dan.

Rate

Join Podchaser to...

  • Rate podcasts and episodes
  • Follow podcasts and creators
  • Create podcast and episode lists
  • & much more

Episode Tags

Do you host or manage this podcast?
Claim and edit this page to your liking.
,

Unlock more with Podchaser Pro

  • Audience Insights
  • Contact Information
  • Demographics
  • Charts
  • Sponsor History
  • and More!
Pro Features