Remix, Server Components, NextJS: Navigating the future of React

Intro

Ben Teese, a web developer, starts with a humorous anecdote about infrastructure developers' tendency to poke fun at new JavaScript frameworks. He shares his go-to response: asking them about their own framework choices, which often leads to awkward silence as they grapple with the ever-evolving landscape of infrastructure tools.

The Rise of Server-Side Rendering

Ben shifts the focus to the recent surge of server-side rendering (SSR) frameworks in the JavaScript world, like Next.js, Remix, and React Server Components. This trend has sparked amusement among infrastructure developers who question why JavaScript developers didn't just stick with PHP. Ben aims to address this sentiment and explore the motivations behind these new frameworks.

The Pit of Success

The concept of the "pit of success" is introduced, referring to tools and frameworks that naturally guide developers towards successful outcomes. Teese emphasizes the importance of both user experience (UX) and developer experience (DX) as measures of success. He argues that while React has been successful in many ways, it hasn't fully achieved this "pit of success" due to challenges in SEO, performance, bootstrapping, and platform utilization.

SEO and SSR

Ben addresses the importance of search engine optimization (SEO). He argues that SSR is crucial for good SEO, as Google's crawlers may not fully execute JavaScript. Without SSR, websites risk being poorly indexed, which can be detrimental for discoverability. He highlights that this doesn't apply to every app, especially those behind logins or corporate firewalls.

Performance Deep Dive

Performance is presented as a crucial aspect of web development. Teese emphasizes the need for clear performance targets and measurement strategies before diving into optimizations. He compares the performance characteristics of single-page applications (SPAs), SSR, and frameworks like Next.js and Remix. He highlights how SSR can improve initial load times by reducing the number of client-server interactions and enabling direct data fetching from the server.

Server Components and Next.js

Server components are explained within the context of Next.js. Ben emphasizes that server components are not the same as SSR; they require a framework like Next.js to function. He outlines the benefits of server components, including the ability to stream results back to the client incrementally, allowing for faster perceived load times. The concept of "zero bundle components," which exist only on the server and never get sent to the client, is introduced as a key advantage.

Static Site Generation (SSG)

Ben delves into static site generation (SSG), explaining how it differs from SSR. He argues that while SSG offers advantages like minimal runtime infrastructure and instant page loads, it has limitations. He uses the example of a website with a dark mode preference to illustrate how SSG can lead to a jarring user experience, as server-rendered content doesn't have access to client-side preferences.

The Future of SSR: Edge Computing

Teese outlines a future where SSR moves towards an edge computing model. In this model, servers and potentially even data stores are distributed across a network, closer to the clients, reducing latency and improving performance. He suggests that this shift is on the horizon and that frameworks like Next.js and Remix are well-positioned for this future.

Developer Experience and Bootstrapping

Teese returns to the importance of developer experience (DX), focusing on the challenges of bootstrapping new applications with React. He shares his experience of building an SSR solution from scratch, emphasizing the complexity of handling routing, data loading, and code splitting. He argues that frameworks like Next.js and Remix simplify this process significantly, providing conventions and abstractions that streamline development.

Next.js: Routing, Layout, and Data Loading

Teese dives into the specifics of how Next.js handles routing, layout, and data loading, particularly in its beta version. He demonstrates how Next.js infers routes from the project's directory structure, simplifying routing logic. He also highlights the framework's built-in support for layouts, allowing developers to easily create consistent UI structures across their applications. Finally, he showcases Next.js's new data loading approach, which leverages server components and asynchronous functions to streamline data fetching and rendering.

Remix: Embracing the Platform

Ben shifts focus to Remix, highlighting its philosophy of leveraging the platform's capabilities. He praises Remix's approach to forms, which prioritizes using native HTML elements and progressive enhancement, ensuring accessibility and a consistent user experience even with JavaScript disabled. He illustrates how Remix allows developers to handle form submissions on the server side using familiar conventions, while abstracting away much of the complexity associated with server-client interactions.

Limits of SSR Frameworks

Ben acknowledges that even powerful frameworks like Next.js and Remix have limitations. He discusses scenarios where client-side state management and UI updates might require additional considerations beyond the default SSR mechanisms. He uses the example of a shopping cart to illustrate how coupling between UI elements can pose challenges for SSR-centric architectures. He suggests that hybrid approaches and careful state management are still necessary in certain cases.

Conclusion: Choosing Between Remix and Next.js

Teese concludes by offering guidance on choosing between Remix and Next.js. He positions Remix as the simpler option with a more opinionated approach and a focus on platform alignment. Next.js, on the other hand, offers more flexibility with support for SSG and the promising, but still beta, server components. He reiterates the importance of measuring performance and having clear targets regardless of the chosen framework. He leaves the audience with a sense of excitement for the future of web development, driven by these innovative SSR solutions.

thanks very much.

Thanks for coming.

alright.

So I work for Shine's actually a consultancy and I only really mention that because we do work across the full stack.

and that means that we have lots of infrastructure developers at Shine, lots of devops people.

and that's a problem for me as a Web person 'cause frankly, Web developers at Shine are probably even outnumbered by infrastructure developers.

And I dunno about you guys, but there's nothing more that the infrastructure developers like to do than to make fun of new JavaScript frameworks.

Every time that they come out, so I just wanna start quickly with my tip on, how to respond when a infrastructure developer makes fun of new JavaScript Web frameworks.

And you know the ones, who will you know, sidle up to you in the elevator and say, so 'Ben, you know what, new JavaScript script framework got released this week?

And they did this to me when Backbone came out.

They did it to me when Angular came out.

They did it to me when Web components came out, which I didn't, I've never even really used Web components.

They did it when Aurelia came out.

You might have heard of that.

Vue of course, and then React, which is whilst we're all here.

And what I've found is the best way to respond to them is to just ask them if they've settled on a framework yet.

For example, have settled on cloud formation or puppet, maybe Chef or Docker, Ansible.

SaltStack, some of you might have heard of that.

Kubernetes was very hot for a while there.

CDK, which I actually quite like personally, cdk, and of course Terraform.

And look, it's grossly unfair for me to consider these to be, similar to one another, but it's enough to shut an infrastructure developer up enough for me to be able to run away.

But things have got particularly awkward and embarrassing lately 'cause there's been a couple of new frameworks that have come out.

New Web frameworks and they're all about rendering on the server side, which causes much hilarious laughter from, infrastructure developers 'cause they don't really understand why we just didn't stick with PHP all along.

So these are things like next and remix and, perhaps, most controversially React Server components, which were announced by the, React core team a couple of years ago.

So what I'm gonna do in this talk is, do a little bit of a, it's a safe space.

So I just want to actually talk about some of these embarrassing questions and ask how did we get to this place where we're talking so much about rendering React on the Server side, what are the sort of problems that have led to it?

And, should we just have been writing PHP all along?

'cause with this stuff I'm just like, let's avoid contact, eye contact with infrastructure developers now when I see them in the hallway.

'cause I'm a bit, I don't even know how to respond.

So who here has heard of the, this idea of the pit of success?

Few of you have.

Yeah.

Okay.

It's I think it's a great way to describe a set of maybe tools and frameworks, even processes that are gonna naturally cause you to gravitate towards a successful outcome rather than an unsuccessful one.

Tools where you have to work harder to fail than to succeed.

That's the ideal for these sorts of frameworks.

I like to think of them as being a bit like this.

Have you ever seen one of these before?

Sometimes they have them at supermarkets and you roll a coin into 'em and mesmerizingly goes around and around.

Really cool.

This is apparently called a hyperbolic funnel, I found out.

and, when we talk about success, let's define that a bit more clearly.

So I'm talking about user experience.

Obviously we want our users to be, delighted by our applications for the applications to be really responsive.

To their needs.

but we also are talking about developer experience as well.

we want developers to actually enjoy working with these frameworks, for them to feel productive, for them to feel that the things that should be easy to do, remain easy to do.

For them to feel that the things that are gonna be hard, are at least possible still.

That's what I call success for the developer experience.

But sadly, we are not there yet, in the React ecosystem.

And there's a couple of reasons for this.

and the first one relates to suboptimal user experience.

Now, this is not to say that every app you build with React is gonna have a poor user experience.

It's just that, the gravity, the, way in which we get pulled by the frameworks we're using isn't necessarily pulling us towards the best experience.

The first front is, search engine optimization.

Which, if you don't think about upfront, is gonna be really problematic for you.

the next is performance.

it's great if you've got a lot of JavaScript running in the browser.

That's a pretty responsive application, but all the JavaScript's gotta get there in the first place.

And I'll drill into that in a minute.

From the developer experience perspective, bootstrapping a new app is still surprisingly hard with React 'cause React isn't really a framework, it's just, it's more of a library than anything else.

You have to make a bunch of decisions and then there's getting the most out of the platform.

'cause we can tend to do things with JavaScript that the platform can give us for free, if we're not careful.

and we can end up re-implementing things that shouldn't have been done before.

And it takes us longer to get things done than it should.

and a lot of the reason for this is, and I recounted a little effectively history of Web development frameworks, before, Backbone brought MVC to the JavaScript masses.

Angular brought bindings to the masses, which was fantastic.

React brought a really good component model to the masses.

but along the way we lost one of the superpowers of the Web, or at least by default, which is hyperlinks, URLs, documents, and the ability for, Google to crawl 'em, for example.

So we've got all this UI code that's shipped into the client side, but where we really need to go is somewhere in between.

We need to be able to get the boas out, best out of a component model on the, in the browser whilst also still retaining, things like URLs and documents.

So that brings us to these frameworks that we're gonna be talking about.

And the first is next.js.

And some of you were probably gonna say, these things have actually been around for a while.

And you're right, next.js has been around for five years now.

It's the original gangster of, Server Side rendering frameworks.

About six weeks ago they actually put out next.js 13 and it's got some really interesting, beta stuff in it, which I'm gonna talk about a little bit.

More recently, we've had remix come out, which is by the guys who invented React Router.

interestingly, a little while ago, not that long ago, remix, that team or the product got bought out by Shopify.

So it's gonna be really interesting to see where that goes.

but they're bringing, brought a really unique perspective to these frameworks.

and finally we've got React Server components, which were actually announced a while ago now.

they've been in like an incubation stage.

they're probably not ready for production yet, but I think that they're really worth understanding because next in particular, has bought heavily into React Server components.

All right, so let's first talk about SEO.

And this is actually gonna be a short section to the presentation 'cause basically if you don't do SSR, you won't really get SEO.

If you do s SSR, you're gonna get SEO.

Like I've spent a lot of time, in the last 10 years musing on how much, JavaScript, so to speak, Google is able to run when it's indexing.

and I think the best thing to assume is that it's just not going to.

you can assume it will and build your whole app in a manner, yeah, as a free for all, SPA.

But you may then get to the point where you discover that Google's not crawling your app, and if that's important to you, you're hosed.

Now that's to say SEO isn't always important.

If you're building an app that requires a user login or even, is in a corporate network or something like that, which is apps that I build sometimes, you don't really need Google to crawl it.

So it's not important, but it is really important to think about this stuff upfront.

if, we look at the original single page app model, you have your JavaScript and you have your index fot HTML file, and then you have some bundler, something like that's going to produce a, a compiled JavaScript bundle, maybe several.

If you're doing code splitting, the browser comes along, loads your single, handcrafted index dot HTML file that might refer to your bundle and you're good to go from there.

Except obviously if you replace the browser with Google's crawler, it's not really gonna be able to make any sense of this.

There's nothing really to crawl except for an empty or largely empty index dot HTML file.

So when we introduce Server Side rendering to the mix, we have our JavaScript script, but now we're gonna produce two artifacts, a Server and a client JavaScript bundles again.

So now browser could go in principle at least to any kind of HTML document that we wanted to.

and those documents may still refer to one of the bundles.

but the cool thing is that you replace the browser with Google search engine and all of a sudden your site's crawlable again.

And we don't actually really need to talk about SEO anymore.

Now I'm gonna move on to the performance side of things though.

And this is in contrast to giant can of worms.

So I'm gonna, preface this with my standard disclaimer when I talk about performance.

And that is that you need to know what your targets are that you're aiming for, and you need to have a way to measure against those targets.

And if you don't or that seems like too much effort, it's probably not worth, optimizing for performance because every performance optimization comes with engineering trade offs.

Past performance is not indicative of future performance, et cetera, et cetera.

What might have worked a little, a couple years ago mightn't really be as applicable anymore.

Really important to keep that in mind.

Just 'cause I'm gonna talk about this stuff doesn't mean you have to go away and do all of it straight away.

I think that when we're talking about performance, it's again good to go through the phases of how these different types of application architectures work.

We've got our client side and our Server side with a single page application.

We've got our handbuilt index dot HTML file, some JavaScript that has maybe been generated for initial load and then, maybe a bundle later on if we're doing some code splitting.

So on our initial page load, if we load that index dot HTML file, we load the main JS file.

But nothing's really happened at that point.

No data's gonna be displayed.

this is just an empty index dot HTML file.

So usually what we have to do is write another data service, maybe like a REST API or something like that.

once our JavaScript has loaded in the client, it's gonna call our data service.

It's probably acting as a proxy for some data store.

Cause we don't wanna expose our database to the outside world and some data comes back.

So we've got three calls there.

On like a subsequent user interaction, when the user does something, we might call that REST service again.

and there may even be another bundle that gets loaded later on.

Now let's contrast that with the simple SSR experience.

And when I say simple, the sort of SSR you might roll yourself, which I've done and highly recommend against.

and I'll get a bit more into that later.

Initial page load.

you've got your, artifacts here and your data service, initial pa page load.

The Server can go directly to the data service.

It can go to the data store.

you can get your JavaScript if you want.

And the great part about this is that we only had to make two calls across the network, between the client and the Server to get that initial page load up and running.

Then on a subsequent interaction, we can go to the data service again, get some more stuff, get our JavaScript.

So remix and next actually take this a little bit further.

You've got your standard artifacts, but you don't actually really necessarily need a REST service anymore to serve up data separately.

So when your initial request comes in, you can get your index dot HTML file and then the Server can go directly to the data store and get its stuff that goes back to the client.

Your main JavaScript might be loaded again, your subsequent interaction, pretty much the same as we had before, except it's going to the same Server.

So these servers can serve up both HTML and data, so to speak, which is cool.

So you've got one less artifact.

That you have to worry about and build and that, is a, good, reason to use these frameworks in itself.

Alright, so now let's talk about Server components and what they might bring to the mix.

And what I'm going to do here is talk about it in the context of next.js, the next version of next.js, which is still in beta, but it's, a good way to think about it.

And I guess for starters, Server side components aren't Server Side rendering.

they need to sit within the context of a framework in this, case next.

So we've got a Server with a couple of components inside it, whatever that means.

on our initial page load, we're going to call that Server and pretty much immediately it can start streaming a result back.

And it might just be, that I'm about to start loading something.

and only then does it really need to load the load, the JavaScript, In parallel the data store can be still contacted by the Server and when it's got the information that it needs, it'll send it back to the client.

And we are pretty much done on that front.

So that's cool.

On a subsequent user interaction, we can do the same sort of thing.

We can call another URL on the same Server and they usually use some sort of scheme, some special scheme for these URLs.

that goes to maybe another component on the Server.

it asynchronously can stream an initial result back whilst it's contacting the data store.

And then at the end, you're all done.

but an interesting part about this is that there's not, you probably noticed a second JavaScript bundle here because Server side components introduced this concept ideally what's called a zero bundle component, zero size component.

that is a component that exists only on the Server.

So all of the JavaScript for that component never needs to go back to the client.

and that's one of the really compelling use cases that they've got for it, along with the streaming.

Now I just wanna do a little aside here on Static site generation, which some of you have probably heard of as well.

next can do this.

remix doesn't do site generation.

I think it's useful to understand why that's the case.

so we've got our original Server Side rendering, like mini architecture there.

Let's think about what Static Site generation is, as an alternative to that.

You have your JavaScript, but from your JavaScript you're actually producing straight up HTML files as well as client bundles.

And all this is done at build time, so we're assuming you've got access to all the data that you need, to put into your fi, into your HTML files at build time.

And then it's pretty much the same sort of deal from then on.

The browser can load any of those HTML files if it wants.

Those files will refer to client side javaScript bundles as they need to.

And lots of people get really excited about static site generation.

I don't get as excited and I think, I'll try and explain to you why.

so with static site generation, let's think about it in terms of caching on a cdn, which hopefully you're all using.

please don't build your own CDN or think that static site generation means you're building your own cdn.

we think about what happens on the first hit between the browser and the Server and the CDN in the middle.

we make our request for a page.

the HTML comes back from the Server.

This is just with straight up SSR, gets cached in the cdn, comes back to the browser.

on a subsequent hit, obviously the browser just goes, sees that the CDN says, I've already got this file.

and it just returns it directly.

The Server doesn't get hit, which is fantastic.

with static site generation, it's pretty much the same sort of deal except with these HTML files.

You call the HTML.

CDN doesn't have, it gets cached by the CDN on the way back through and subsequent hits pretty much the same deal as what we had before.

So sorry to put you through all of that, 'cause obviously these look very much the same.

I guess the thing is, the only real difference between these two approaches is that the user had to endure the rendering of the initial page if you're just using straight up SSR.

Whereas with static site generation, the user does not have to endure that pause.

otherwise they're pretty much the same.

I guess another advantage of static site generation is that you don't necessarily need any infrastructure or certainly not runtime, compute infrastructure to serve stuff up, which is pretty cool.

But otherwise, there's pretty much not a huge advantage to static site generation that I can see.

And I've had clients who get really excited about this and then they add up, add everything up, and realize they've got 50,000 pages that they'd have to build at build time and the appeal drops off all of a sudden.

And the re I think the remix team have recognized this and that's part of the reason, frankly, that remix doesn't support static site generation outta the box.

And if you really want to, ensure that your very first user to a particular page doesn't have to endure that way, you could always just prime the cache by calling it yourself post-deployment.

And there are also limits to static site generation, but to be fair also to static, to Server Side rendering.

So here's the material UI page for example.

it's got dark mode, which is fantastic.

so I'm just going to reload my page and it flashes white and then back to black.

What happened?

Let's try once again.

Anybody got any idea what happened, what might have happened?

Correct.

not even cookies actually, in this case it's in local storage, but same kind of deal.

Yeah.

this, site is built with next, whether they're using static site generation, I don't know.

but either way, the backend doesn't know that I want it in dark mode or not.

All it can really do is send me one thing, so it sends me the white version of the page.

then everything loads on the front end and it looks in local storage and says, oh, this guy actually wants dark mode.

So it flips it to dark mode.

So I have to endure that flash.

and this is a pretty significant limitation, not just of SSG, but also of SSR.

Because if, for example, you did put it in a cookie, and sent that to the Server and looked at the cookie, the Server could generate a dark version of the page for you.

But then what happens with the cdn?

are you gonna case that, what version of, what do you case?

How's that all gonna work?

So I think that as our websites, as personalization becomes more of a thing, even for such trivial stuff as whether you are in dark mode or not I think there's a bit of a change in model that we're gonna be seeing in future.

CDNs will still be a part of it, but not necessarily the final word in the story.

'Cause at the moment we have this idea of centralized SSR where we have our Server or even servers, but still running inside one particular region alongside a data store.

And then the clients come in and they all call that Server pages get cashed in the cdn.

But where we're going, and this is, frankly the way in which next, in which next and Remix are probably gonna make money in the longer term, is more towards an edge model where these servers are running in an Edge network closer to their clients.

The clients can call those servers, which might then go to a data store.

Now the savvy amongst you will then go, oh, what about the data store then?

Isn't that the bottleneck?

'Cause usually the data store is the bottleneck.

you can have as many application servers as you want.

So now then we're looking at potentially even an even more sophisticated model where you have both the data stores and the servers all sitting out in the edge network.

So clients call your data, call your servers.

They go through the, to, to their respective data stores.

And then these data stores are smart enough to synchronize amongst themselves.

this is a model.

It's a little bit over the horizon, but I think that it's one that we're going towards a lot, and the builders of these frameworks recognize that.

All right, so that was the big performance section.

Now let's talk a little bit about developer experience, and especially the experience of bootstrapping a new application.

so I mentioned earlier that I've built, Server Side rendering pretty much from scratch myself.

Actually, I, that was in consultation with Mark Dalgleish he gave us some great advice on it, and this was several years ago.

And, despite Mark having, been down that path before, it was still a giant pain for us because we had to learn the hard way that, routing, when it comes to Server Side rendering is they're tied up with one another intrinsically, and then there's data loading.

The way in which you load data, you've gotta make decisions about how you're gonna do that.

And then there's code splitting.

Oh my goodness.

Just the kind of the confluence of code splitting, routing, data loading and Server Side rendering makes your head explode.

you don't wanna do this yourself, but this is why these frameworks were invented.

And they also bring other things to the mix as well.

For example, just the notion of how you're gonna structure your project and the fact that they can automatically then map it to a set of routes.

That's really cool.

And finally, the way in which you lay out pages and how that relates to file structure and how that relates to routing.

You can invent all of this stuff yourself from scratch each time if you want.

but you're gonna be learning the hard way.

I advise just using a framework.

So I'm gonna show you in a little bit more detail how this works with next.js, 'cause I'm kinda limited for time I'm not gonna be able to do it, like for like with remix but similar kind of deal.

This is the next.js beta though, and the way in which next deals with data loading and routing and Layout has changed a lot, with the very latest version.

Just keep that a little bit in mind.

But the great thing about next is that it can just look at your directory layout, and from that infer what you are routing is gonna look like.

So in this case, we've just got an application and it's got a page file, a root page dot jsx file, and that's gonna respond to the root route for the project.

there might also, there can be other files as well.

like a folder for example, has dashboard information inside of it.

That's just automatically gonna infer that's a dashboard route.

you can even nest these things even further and deal with dynamic path segments, which is pretty cool.

And you'll notice there's some other files in here too relating to layout, error handling and loading.

Just the mere presence of these files means that, next we'll pick them up and use them to draw your, UI in the case that there's a problem or that needs to do some data loading.

And you can nest these things as well.

You can nest layouts within layouts, which is pretty sweet.

So for example, here is, what a root layout file might look like not really doing much, just delegating to some children.

But even better, each sub directory of its own can have its own layout and it'll nest it automatically for you, which is pretty cool.

But where things get really interesting is when it comes to data loading.

and this is where we start to talk about, Server side components a little bit.

So here's, for example, a nested, component for a page.

and it's actually loading product information.

Now this might look a little bit, a little bit weird, because it's got, it's got a fetch in it.

But by default in, the new version of next, every component is assumed to be on the Server side only initially.

You have to explicitly say that it's gonna be a client side component, which is a pretty big change in mindset to what we might've done before.

So in this case, this is actually a Server side component that's gonna make a fetch call.

to a backend to get some data relating to a particular product for example.

Another crazy thing about this is, that you can see that it's an async function too.

so the Server is able to deal with the fact that we now have a React component that is an asynchronous function.

And it will automatically deal with displaying the correct loading states, displaying errors in the event that there's a problem loading this data.

But you can see that then when I load the product, what do I do with it?

What is this product component?

I've got another little file there called Product dot jsx with a capital P because with next.js, you don't just have to use their files.

they've got their file name in conventions, but you can introduce your own components and co-locate them alongside.

And that's what I've done here.

Even more interestingly, this component is actually gonna be a client side component.

And we'll make it that way because say that we've got, we want some states, some client side state, just maybe you click something and it expands out the details of that component.

that's exactly what we're doing here.

This data, this product data is being passed in from a Server side component to the client side component, which you can actually do.

There's some restrictions on this.

Restrictions on this.

for example, you can never have a Server component running in the client.

but you can certainly have client components running or that are executed inside the Server.

And then hydrated and sent to the client.

And then from that point on, once they'll run purely within the client, which is pretty cool.

And this is really what Server components are all about.

This is the future that we're talking about.

A future where components run on the Server by default.

They load data by default on the Server side.

And I've been a big fan of GraphQL in the past, and still use it for some projects.

But to be honest, this new architecture that they're proposing will obviate the need for things like GraphQL for certain types of applications .

Not all, but for some of them.

So that's an example of how, next solves a lot of these problems for you out of the box.

But then there's the idea of using the platform and I think Remix is a really good example of a framework that does this.

my favorite is just forms.

So you know, they have seen big React form frameworks that have been used and have said, no, we've got a lot of this stuff in the browser already.

You can just describe with HTML.

Having a form in remix is as simple as just bringing it a component and swapping out, the form tag from lowercase to uppercase.

And, it will operate as a normal form if, for example, your JavaScript is turned off in the client and even submit to the right place.

And if JavaScript is switched on, it can do progressive enhancement.

And this is actually pretty cool to see.

Now I know people don't wanna fetishize switching off JavaScript in the client 'cause to be honest, people don't really do it.

but it is a good North Star to aim for when you're thinking about progressive enhancement.

You're probably wondering, what happens with the Server side of this when this thing gets posted?

And what remix can do is pretty much in the same file, you can export another function.

And this is a function that'll get executed on the Server side when this form data is submitted.

And the cool part about this is remix has been able to figure out, oh, this code is potentially executed on the client and the Server side and this code in the same module will be executed only ever on the Server side.

'cause for example, you know I'm talking directly to a Prisma database here, which is pretty sweet.

And again, it's using kind of some pretty old school constructs there.

Like you'll see at the bottom that after the action's been performed, it'll do a redirect to your URL and it'll be able to automatically figure out where it should go and to make sure that it's a good experience for the user.

So it looks pretty much as much like a, a traditional form, dare I say, a PHP style form is as you're gonna get these days.

Remix is also pretty savvy about caching.

Like I said earlier, they're not massively into static site generation.

Instead, they encourage you to use, good old-fashioned cache headers as much as possible.

So a component or a component for a route specifically can export another thing that just describes the headers that should go out with that, the page for that particular route.

And you can just use classic cache control headers here.

You're not having to learn a new system for caching or anything like that.

That said, I think it's important with both of these frameworks to understand that they have some intrinsic limits.

like even with the forms, for example.

sometimes the forms that I was showing you just then, the validation was only ever gonna occur when you sent the form to the Server.

But that won't necessarily be a good user experience.

Sometimes you want a form to be responsive and you do want some JavaScript in there.

You don't want there to be a round trip to the backend.

So these solutions will only take you so far.

They provide a pretty good path to it though.

Another, limit is, and I call this kind of the shopping cart problem.

Imagine you've got, your classic shopping cart.

Or shopping application with your cart with a counter up in the top right hand side, you click add to cart to buy the unicorn.

we want that counter to increment, but if we think about what this component hierarchy would look like, really there's the counter and the add to cart button are in completely separate places in the component hierarchy, but they're, coupled to one another.

there's no denying that.

So how do we deal with that coupling?

In a, PHP application the whole page gets re rendered so we can be confident that the UI is gonna be updated effectively, but that's not necessarily gonna be the case with a single page application.

How do we know what parts of the UI to update?

and this is where things get a little bit stickier.

It's worth understanding the limits.

If you're doing this with remix, sure you'll have a good old form post, but every time you submit a post, submit a form, it's gonna reload all the data for all the routes.

that's not a full page reload, but that data is gonna be sent back to the client, and it will selectively update what's happening in the browser.

Won't override any state, but it has to reload all the data at the back end.

when it comes to Next.js , you've gotta be explicit about doing that refreshing.

This is a bit of a work in progress.

You tell the router to refresh and it will again, load all the data from the root layout downwards.

You'll still retain client side state, but this is a problem that's still in play.

the, in fact, the next team have got an RFC for mutating state and finding ways to do it more efficiently in play at the moment.

All right, so let's wrap this up.

in short, if you need SSR, use remix and Next, don't try and do this stuff yourself.

And perhaps a bit more controversially, if you don't need SSR, it probably would still be a good idea to use Remix and Next.js, just because they give you so many solutions out of the box for all the things that I talked about.

yeah, of course.

Then the next question is gonna be inevitably, which do I choose, remix or next.js?

I'd say remix is simpler.

There's really just one way to do things with remix.

whereas with next, really there's four ways to load data, and deal with caching and describe pages and put data in pages.

remix just has one approach.

And remix also makes the most out of the platform.

So there's a little less, learning that you have to do.

next.js on the other hand, does support static site generation if you really need it.

but it's important to make sure you really need it.

It also gives you Server components, which are pretty cool, but are still in beta.

I'm excited about them, but again, all the performance benefits that I've talked about are theoretical, so it's important to measure and have targets just as before.

And that's pretty much it for me.

Thank you.

How to respond to infrastructure developers who make fun of new web frameworks

  • Backbone
  • Angular
  • Web Components
  • Aurelia
  • Vue
  • React
  • Next.js
  • Remix
  • React Server Components
  • CloudFormation?
  • Puppet?
  • Chef?
  • Docker?
  • Ansible?
  • SaltStack?
  • Kubernetes?
  • CDK?
  • Terraform?

the pit of success

photo of a boy rolling a coin into a charity collection contraption. A banner appears over the top after some time saying 'we are not here yet'. To the right appear as Ben speaks the following points

  • Sub-optimal UX:
    • SEO
    • Performance
  • Sub-optimal DX:
    • Bootstrapping a new app
    • Getting the most out of the platform

Where are we going?

A box representing 'client-side' (with a smaller box labelled "UI Code" inside it) sites above a box labelled "server-side"

Where are we going?

The box labelled "UI Code" now covers part of both the client aside and server side boxes.

"Next.js" now appears to the right of the boxes

"Remix" is now added

"React Server Components" is now added

SEO

Diagrams representing Single Page Application (SPA) and Server-Side Rendering (SSR) architectures. The difference is that for SSR, "your JavaScript" generates the server based HTML as well as the Client JS Bundle, where with SPA, your HTML is developed separately.

Performance

As Ben describes the phases of how these different types of application architectures work, the slides build a complex diagram that mirrors his description.

Static Site Generation

As Ben describes the architectures of server side rendering and static site generation. As he does the slides reflect his description.

The limits of SSG (and SSR)

Ben reloads the material UI web page, in dark mode and it flashes in light mode before reverting to dark mode when the page is reloaded.

Centralised SSR

As Ben describes centralised SSR, the slides reflect his description.

Centralised SSR

Edge SSR

As Ben describes edge SSR, the slides reflect his description.

Edge SSR

Edge SSR + Data

As Ben describes edge SSR plus data, the slides reflect his description.

Bootstrapping a new app

As Ben describes bootstrapping a new app his slides reflect the architecture he describes

Text based representation of the directory structure of the next.js app. Ben describes important features and these are highlighted on the slides as he goes

app
	layout.jsx
	page.jsx
	error. jsx
	loading. jsx
	dashboard
		page.jsx
		settings
			page.jsx
products
	layout.jsx
	[id]
		page.jsx
		Product.jsx

from the directory structure, layout.jsx, an arrow points to the following code


export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

from the directory structure, page.jsx, an arrow points to the following code


import Product from "../Product"
async function getProduct(id) {
  const res = await fetch(`https://product-api.example.com/${id}`);
  return res.json();
}
export default async function ProductPage({ params }) {
  const product = await getProduct(params.id);
  return <Product product={product} />;
}

from the directory structure, Product.jsx, an arrow points to the following code

Forms with Remix

Forms with Remix


<form method="post" action="/customers/new">
  <p>
    <label>
      Name:
      <input type="text" name="name"/>
    </label>
  </p>
  <p>
    <label>
      Address:
      <textarea name="address"></textarea>
    </label>
  </p>
  <p>
    <button type="submit">
      Create
    </button>
  </p>
</form>

export async function action({ request }) {
  const formData = await request.formData();
  const name = formData.get("name");
  const address = formData.get("address");
  await prisma.post.create({
    data: { name, address }
  });
  return redirect("/customers");
};

The Platform: Caching with Remix


export function headers({
  actionHeaders,
  loaderHeaders,
  parentHeaders,
}) {
  return {
    "Cache-Control": "max-age=300, s-maxage=3600",
  };
}

The limits of these frameworks

Ben describes building a shopping cart form and the elements on the page and their relationships and the slides reflect that

Mutations with Remix

Reloads all the data for all the routes


import { Form } from "@remix-run/react";
…
export default function AddToCartButton() {
  return (
    <Form method="post">
      <button type="submit">
        Add to cart
      </button>
    </Form>
  );
}

Mutations with Next.js (Beta)

  • Refreshes data from root layout
  • Retains client-side state
  • RFC for mutating data in the works

"use client";
import { useRouter } from "next/navigation";
export default function addToCart() {
  const router = useRouter();
  return (
    <input type="button" value="Add to cart" onClick={() => {
      // Make REST API call to add item to cart
      ...
      router.refresh();
    }} />
  );
}

Let's Wrap This Up

  • Need SSR? Use Remix or Next.js
  • Don't need SSR? Probably still use Remix or Next.js
  • Remix:
    • Simpler
    • Makes most out of the platform
  • Next.js:
    • Supports SSG
    • Gives you server components (beta)

Thank you

ben.teese@shinesolutions.com