Conf42 JavaScript 2022 - Online

Treat your users right with segmented rendering

Video size:

Abstract

Jamstack, SSR, SSG, static rendering, Next.js, Gatsby, ISR, prerendering, edge handlers… JavaScript developers sure like making up new words!

But what do they mean, actually? In this talk, I’ll demystify those fancy concepts and propose a better definition of “server-side rendering” a web app.

You thought “server-side rendering” and “static rendering” were different things? That you cannot render authenticated, paid or personalized content at build-time? That per-request SSR costs an arm and a leg? Then this talk will blow your mind!

Based on this corrected definition of SSR, I’ll show you how you can solve the “rich guest/poor customer” issue that arises when you don’t use static rendering to its full potential. The result: ultra-personalized static websites, that cost nothing to host and deliver the best possible user experience.

Segment your renders and make your customers rich again!

Summary

  • Jamaica real time feedback into the behavior of your distributed systems. Errors in real time allows you to not only experiment with confidence, but respond instantly to get things working again. Treat your users right with segmented rendering.
  • Eric Burel is the founder of a company based Elbecau. He is also the maintainer of the open source framework vulcanjs. Also a next JS teacher at human coders. You can find him on Twitter and medium.
  • Most common example of web personalization is theming. Anything that adapts a website to who the user is. Dynamic patterns can adapt to the current request or user. But they are slower because they need to do a new computation for each request. Segmented rendering is a way to use the static pattern for personalized content.
  • The idea of segmented rendering is that I don't want the theme to appear in the URL. This means that things personalization doesn't require a new computation. It applies to any kind of personalization where you can define a segment. Finally I use a URL rewrite to rewrite the URL of the request.
  • Nextjs can create a new version of the page on the go on the first request. Based on this we can renders different themes. This is all open source. It's actually really a few lines of code and using approach that you already know.
  • Segmented rendering will be translated as edge personalized at the costs level. Because it happens at the edge. The idea is that the personalized is very fast and because it happens near the end users. This is typically useful if you have a global company.
  • Nextjs 13 changes the way next JS server side rendering is structured. Segmented rendering is about avoiding to call those functions when it's not needed. In the future we will have a unified API that encompasses static, perrequest and everything in between.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Jamaica real time feedback into the behavior of your distributed systems and observing changes exceptions. Errors in real time allows you to not only experiment with confidence, but respond instantly to get things working again. Those everybody, and welcome to my talk. Treat your users right with segmented rendering. Let me start by introducing myself. My name is Eric Burel. I live in France, in Montpellier. I'm the founder of a company based Elbecau. I'm a web developer. I'm doing a lot of things. I'm doing consulting in public funding for a company named Research to business. I'm those maintainer of the open source framework vulcanjs that used to run on top of meteor and is now working with NextJs. I'm a member of the devographics collective who runs the state of JavaScript costs and graphQL surveys created by Sasha Graph and I'm a next JS teacher at human coders. You can find me on Twitter and medium. So this talk is essentially about web personalization. So let's start by defining it. I think the most common example of web personalization is theming. It's just, for instance, letting a user pick version of the website they like. Here I have free themes, firewater and grass. Of course, usually in real life the theme will be about dark versus light mode, for instance, but it could also be an adaptation to a certain company, having your own logo or picking your own colors for a website. So web personalization is anything that adapts a website to who the user is and usually knowing who the user is. ISR actually implemented using cookies. For instance, I will have a cookie name starter with the values fire, water or grass that will define the themes I picked. But you are already used to use personalization in a lot of different contexts. So for instance, you have the same use case, but you have internationalization, which is a form of web personalization because you adapt a website to the language of the user that you detect based on the request headers or cookies. There is the paid versus unpaid content and guest content. You have a b testing. That's one very advanced example of web personalization where you change a version of the website to make an experiment. For example, you have half the user with a version can old version and the other half with a newer version that you want to experiment and you compare the statistics for both things is an example of web personalization. So it's kind of ubiquitous in web development. So let's focus on this theme use case and let's try to render the right those based on the user information. So first let's define this idea of rendering. What do I mean by prerendering? Nextjs is a good platform to understand rendering because it embeds all modes of prerendering of server rendering and client rendering. So the first one, client rendering is just using javascript or treat or whatever front end framework you are used to use when creating single page application with a lot of interactivity and javascript. That's good. Old client side prerendering, server side rendering or per request server side rendering is what you are used to do if you code with PHP, Ruby, django, a language that is not node JS, basically a traditional web server. And static prerendering is a variation of server rendering where you render the page ahead of time and not for every request. It's just like putting your server render into a cache or just writing HTML ahead of time that is not adapted to the current user, to the request. So basically, client side prerendering and per request server side rendering are dynamic patterns. Why? Because they take the current users into account. Serverside rendering happens for each request, so you can adapt the answer based on the request content. So based on the cookies, the user information and stuff like that. Client side prerendering happens in the browser. So of course it's adapted to the user because it's literally running on their machine. Static treat generation is, well a static pattern, but it has the advantage of being faster since the page, the HTML of the page is generated ahead of time. So there is no new computation for a new request. But the problem is that you cannot adapt the content to the request because it's already on the end. It's too late when the request happens. So what to use for personalization? The answer is really the dynamic patterns. Of course they are dynamic and they can adapt to the current request or user. The problem ISR that they are slower because they need to do a new computation for each request or for each interaction between the user and the browser. So ideally we would like to use static generation to get better performances. And segmented rendering is exactly about that. A way to use the static pattern for personalized content. Let me rephrase things idea in terms of business concept. When you use dynamic patterns for web personalization, you are faced with what I call the rich guest per customer issue. The problem is that you are using those faster static renders for public content that is not personalized and you are using the slower dynamic patterns for personalized content. But personalized content is usually for your customers, for the people, you know, for the people that are logged in, for instance for the paid users of your application. So people pay to access your website, pay for your ecommerce website, they provide their data and so on. And yet you treat them less. You give them worse performances than the people that are not connected, those guest of your website. That's the rich guest, poor customers issue. So let's solve this with segmented rendering. So the most basic way to implement segmented rendering is to use the URL, those patterns words. Okay, for example here we could have the theme firewater and grass as a URL, a root parameter of the URL, an explicit parameter. You may be used to this pattern. For example, for internationalization, it's common to have fr en, to say France, England or whatever, to have the language in the URL. And it's okay for many use cases. However, there are a few issues. First, the user can change the URL that's okay for the language, that's not okay for paid content. Of course they can see the parameter okay for internationalization. But if you are doing an A B test, you can throw it into trash because if the user is aware of the bucket they are in, it's useless. The test is just broken. So you cannot do that for a b testing. It's not safe. And finally, when you have a lot of parameters, the URL will become quite long and ugly. You cannot show anything, any parameter in a URL that's not those same way to personalize a website. Okay, so let's have a second try without the URL. This time I need a very small addition to my architecture. I need to add what we call a proxy server, a tiny server that is just able to take your request and to change the URL server side. And then it will point to the right page. This is a very subtle change compared to just using the URL, but very important because this URL rewrite is happening serverside and it isr not known by the end user. So the user is just accessing the website and the URL parameter is added after server side. It's a kind of server side rerouting of the request and it's very powerful because it will solve all our issues in one go. The user won't see the parameter, it's added serverside. Those URL doesn't become ugly because the parameter is not visible and you can do everything securely. For example, adding a paid parameter securely because it happens server side, the user cannot alter the parameters manually. The parameter itself can be computed based on the request, typically based on a user id you get from the cookies session token that allows to identify the user uniquely server side. But again it's safe, which is great compared to the URL. And this is just segmented rendering. That's it. You just have to add this tiny redirection server and it opens up this new pattern that lets you statically render personalized content and get the best performance for your customers. One URL per segment and a rope server. This might sound a bit abstract to be fair. So I wanted to show you now a possible implementation with next JS middleware. Because next JS edge middlewares can play the role of the proxy servers I've described earlier. It's specifically running at the edge. Of course it could work with more traditional architecture, for example with an NginX proxy server. But in nextjs the advantage is that it's built in the framework. You can collocate this serverside and your nextjs code, and in addition it's written in JavaScript, so it's more intuitive for front end developer than say Nginx or configuring your AWS gateway or any solution that is targeted at DevOps, while nextjs middleware are targeted more at Javascript developers. So let's proceed with the demonstration. Let's get started by discovering the end result of segmented rendering. So I have a simple demonstration website, you can find the link in the slide and I will share that where relevant. So basically I have this website and I let the user explicitly select a theme between fire, water and grass. Okay? And the idea of segmented rendering is that I don't want the theme to appear in the URL and I want the theme selection process to be secure because for a theme there is no critical issue of course, but I want this pattern to work also for paid content, for secure content, for IB test, for whatever. I want a very generic pattern. So here I have no theme currently and I will select the fire theme. Okay, the page refresh and the current, those is fire. You see that the text becomes red. So first thing to notice, it's slightly small on my computer. But basically you see were that the URL is not changed, I don't have a fire parameter, I don't need it. Second, you can notice in the network tab, for instance if I do a hard refresh, that the result returned from the server is already personalized current those fire I don't have the css, so you won't see the color, the actual color in the development tooling. But you see that the text is correct. So this means that this was server renders. However, this was statically server rendering, meaning that I did not need a new computation. I cannot prove that in the browser because you cannot see what happened in the server, but I will show you the corresponding code that is using only the static features of nextjs and not per request. Server side rendering. This is very important. This means that things personalization doesn't require a new computation. If you have 3 million people using the fire theme, there is only one render and not one render for each of the those million request. That's the big difference with dynamic patterns. And it's faster because it's already renders as well. So the current those ISR statically renders to define and to remember the corrected theme. I've set up a cookie, a theme cookie that can be read by the server on each request to select the right theme for the current user. As simple as that. And this pattern is very interesting because as said earlier, it applies to any kind of personalization where you can define a segment where multiple people may have the same version of the website. Like can a b test where you have two groups with many people in each group. Like a language where world country will use the same language and stuff like that. So let's take a look at the code. First, it starts with the middleware, which is the most important part of my segmented rendering architecture. It's the proxy server I've shown earlier. So the middleware ISR really simple when I mean it's a light server. It's a light server. There are more concepts than code here. So the middleware will just take the request, read the theme cookie, it can check that the theme is valid. So if the user try to use a those that doesn't exist, well they just cannot. I can throw an error or I can have any kind of behavior I want and I can do that server side so it cannot be hacked by the user. So it would work very well with paid content, for instance. Then finally I use a URL rewrite to rewrite the URL of the request. It's important to notice that it is not a URL reguration, but can actual rewrite. The difference is just that a reguration ISR visible to the end user. A rewrite is not, it is internal to the server. And that's why the end user dont see the personalization parameter. It's happening on those server side. It's kind of rerouting a request on the server to match another URL without the user knowing it. Okay, the second part of the segment and rendering architecture is the rendering part. Here I have redirected the user by detecting the right segment based on the cookies so the those and corrected them to right variation of the website. But I need to actually render the different versions of the page, different themes for the same page. So to do so I will use the API of next js get static path and get static props. If you are not familiar with nextjs, static path is about defining which version of the page you want to statically renders. So here for instance, I'm pre rendering a fire version, a water version, a version without a those, and I voluntarily omit graph because I want to demo incremental static regeneration which isr basically the ability of nextjs to create a new version of the page on the go on the first request. So for instance, if a combination of parameters is not very common, you may not statically render it, but instead render it on the first request. Then it will be put in a cache and reused for further request. But it's important for those who are already wondering how we will be able to handlers a website with a lot of variations. The answer is that you statically renders the most important variations, a few of them, and then you used this pattern, this incremental static regeneration which exists also with other names in other frameworks. There are other approach to do so for other variations. Those idea is just that you put everything in a cache to reuse them later, so that one render is shared by all users of a segment. Get static props for each path will compute the data of the page. So here it's just the theme itself. But we could also for instance get more information about each theme in a database or something like that. Then this parameter is just paste to the page. So the those component receive the those as props. As simple as that in HS. And based on this we can renders different themes. So for example here I'm selecting different styles based on the theme, the current theme value. So that's the rendering part. I'm configuring my rendering framework. So nextjs gets p whatever to statically render each possible variation of the patch. This is not those hard part. If you are used to static prerendering, things will feel very normal. It's just static seed generation. It exists with many technologies and those smart idea is just to say I'm going to generate variations even that are not really static, like paid content versus free content. And I will put a middleware in front of them to pick the right variation. I've computed ahead. I know it sounds a bit unsettling at first, but you see from the demonstration and you will have access to the code. Again from the slide there is a link. This is all open source. It's actually really a few lines of code and using approach that you already know. You already know what a URL redirection, what a URL is, you already know what a request is and you already know what static rendering is if you are used to create full stack application or to those frameworks. So I'm just combining the simple approaches to create to achieve an optimal number of renders. Small bonus. I'm using an edge API route to select the right theme. So I'm using an HTTP cookie basically to set the theme. This can be useful if you need more security on the cookie. So for example, based on those unique identifier for an A B test bucket you might want to use such patterns. So I'm switching the those using only server side code and not client side Javascript. So this demonstration should work without Javascript enabled. That's the small bonus. It's not mandatory, but that's the small bonus for this application. So let's get back at the slides. Now this has been a long ride, but here we are. We have implemented segmented rendering and demonstrated the implementation with next js. If you are exploring the versel website, Versaille being those company behind Nextjs, if you don't already know it, they will use segmented prerendering but give them the name of edge personalization. This is because in Versailles, for instance, the proxy server is implemented at the edge. The edge is just having a cload of tiny servers that are close to the user. The idea is that the personalized is very fast and because it happens near the end users. And this is typically useful if you have a global company for instance, that operates in multiple country, you may have segments that are defined by regions, for instance. So segmented rendering is very appropriate in this context and it will be translated as edge personalized at the costs level. Because it happens at the edge. You will see this naming also with competitors of Versailles, for example netlify is implementing edge features. Eleventi is doing another kind of edge personalized as well, which is more about altering the HTML than using this redirection approach. But that's something you might hear about in the ecosystem. I've picked another name, segmented rendering because I still want to have a definition of this pattern that is not specific to the those stagnant rendering is just my generalization and formalization of things pattern that you may encounter in practice in the industry. Vih personalization. So I'd like to conclude on the future of SSR. Actually maybe the current of the SSR, because I'm registering things talk right after the nextjs 13 release, and if you don't know it already, it completely changes the way next JS server side rendering is structured. The segmented rendering demonstration still hold. Those implementation is slightly different if you know, if you are already aware of next JS inner workings. Basically you have the headers and cookies function, and segmented rendering is about avoiding to call those functions when it's not needed. So that's something we may have the chance to discuss, and I may have the chance to talk more about if you follow me on Twitter. Or you can meet me on the nextjs discord and they are very often talking about such patterns. But basically the future of server side prerendering ISR about caching, it's about forgetting this static versus per request server side rendering idea and just thinking that it's about caching. So static rendering is just server side rendering cached at build time. And the idea of segmented rendering is just that a tiny server lets you pick the right cached value. It's just a cache key actually, and per request serverside rendering is when a value render cannot be cached. It can happen in some situation when the data are heavily personalized, for instance, you cannot put them in cache. It works here because I have segments of users that will have the same version of the page, basically. So the cache key is not just the URL, it's the full request, and the cache value is the renders HTML. And the middleware lets you compute the right key for each request, translate the request to a URL that acts as an intermediate cache key. So my bet is that in the future we will have a unified API for server side rendering that encompasses static, perrequest and everything in between. It's a relatively safe bet, given that again, the next GS 13 release is really about that they actually started to unify the IPF or serverside rendering. However, it's still heavily based on the URL more than the request. So you still have to use this middleware trick to implement segmented rendering. While I hope that in an even further future, instead of having defining the variation of your page based on the URL, you could use those perrequest directly, because this is actually what's happening under the URL is just a simpler way of doing this, but it's actually all about request. I hope you enjoyed this talk. I've put a lot of additional resources at the end if you want to get more familiar with this pattern with personalization which is very useful in the industry. If you are dont ecommerce, a b test and managing website at scale, you cannot avoid web personalization. So I've put my preferred resources and a few articles that shows various variation of segmented rendering like the megaparam patterns that can let you scale it or how plasmic use it in a no code approach which is also very interesting. I hope you enjoyed this talk and I hope you will enjoy the rest of the comfort conference. See you soon. Thank you.
...

Eric Burel

Computer Science Engineer @ LBKE - Vulcan

Eric Burel's LinkedIn account Eric Burel's twitter account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways