{"id":25,"date":"2021-11-28T06:25:30","date_gmt":"2021-11-28T06:25:30","guid":{"rendered":"https:\/\/techwyns.com\/tech\/blog\/2021\/11\/28\/types-of-ip-address-and-its-requirements\/"},"modified":"2021-12-31T01:05:33","modified_gmt":"2021-12-31T01:05:33","slug":"types-of-ip-address-and-its-requirements","status":"publish","type":"post","link":"https:\/\/techwyns.com\/tech\/blog\/2021\/11\/28\/types-of-ip-address-and-its-requirements\/","title":{"rendered":"client-side-vs-server-side-pre-rendering"},"content":{"rendered":"\r\n\r\n\r\n\r\n\r\n<p>There&#8217;s no question that user experience is impacted by perceived load times. With today&#8217;s heavier front ends, client-side rendering doesn&#8217;t feel very fast. In this article, TechWyns Freelance Front-end Developer Matthew roberts compares client-side, server-side, and pre-rendering strategies to help you choose the best option for your own app.<\/p>\r\n<p>&nbsp;<\/p>\r\n<p>There is something going on within the\u00a0<a href=\"https:\/\/www.toptal.com\/front-end\">front-end<\/a>\u00a0community recently. Server-side rendering is getting more and more traction thanks to React and its built-in server-side hydration feature. But it\u2019s not the only solution to deliver a fast experience to the user with a super fast time-to-first-byte (TTFB) score: Pre-rendering is also a pretty good strategy. What\u2019s the difference between these solutions and a fully client-rendered application?<\/p>\r\n<h2 id=\"client-rendered-application\">Client-rendered Application<\/h2>\r\n<p>Since frameworks like Angular, Ember.js, and Backbone exists, front-end developers have tended to render everything client-side. Thanks to Google and its ability to \u201cread\u201d JavaScript, it works pretty well, and it\u2019s even SEO friendly.<\/p>\r\n<p>With a client-side rendering solution, you redirect the request to a single HTML file and the server will deliver it without any content (or with a loading screen) until you fetch all the JavaScript and let the browser compile everything before rendering the content.<\/p>\r\n<p>Under a good and reliable internet connection, it\u2019s pretty fast and works well. But it can be a lot better, and it doesn\u2019t have to be difficult to make it that way. That\u2019s what we will see in the following sections.<\/p>\r\n<h2 id=\"server-side-rendering-ssr\">Server-side Rendering (SSR)<\/h2>\r\n<p>An SSR solution is something we used to do a lot, many years ago, but tend to forget in favor of a client-side rendering solution.<\/p>\r\n<p>With\u00a0<strong>old<\/strong>\u00a0server-side rendering solutions, you built a web page\u2014with PHP for example\u2014the server compiled everything, included the data, and delivered a fully populated HTML page to the client. It was fast and effective.<\/p>\r\n<p><strong>But\u2026<\/strong>\u00a0every time you navigated to another route, the server had to do the work all over again: Get the PHP file, compile it, and deliver the HTML, with all the CSS and JS delaying the page load to a few hundred ms or even whole seconds.<\/p>\r\n<p>What if you could do the first page load with the SSR solution, and then use a framework to do dynamic routing with AJAX, fetching only the necessary data?<\/p>\r\n<p>This is why SSR is getting more and more traction within the community because React popularized this problem with an easy-to-use solution: The\u00a0<a href=\"https:\/\/reactjs.org\/docs\/react-dom-server.html#rendertostring\" rel=\"noopener noreferrer\"><code>RenderToString<\/code><\/a>\u00a0method.<\/p>\r\n<p>This new kind of web application is called a\u00a0<em>universal app<\/em>\u00a0or an\u00a0<em>isomorphic app<\/em>. There\u2019s still some controversy over the exact meanings of these terms and the relationship between them, but many people use them interchangeably.<\/p>\r\n<p>Anyway, the advantage of this solution is being able to develop an app server-side and client-side with the same code and deliver a really fast experience to the user with custom data. The disadvantage is that you need to run a server.<\/p>\r\n<p>SSR is used to fetch data and pre-populate a page with custom content, leveraging the server\u2019s reliable internet connection. That is, the server\u2019s own internet connection is better than that of a user with\u00a0<a href=\"https:\/\/developers.google.com\/web\/fundamentals\/performance\/poor-connectivity\/#what_is_lie-fi\" rel=\"noopener noreferrer\">lie-fi<\/a>), so it\u2019s able to prefetch and amalgamate data before delivering it to the user.<\/p>\r\n<p>With the pre-populated data, using an SSR app can also fix an issue that client-rendered apps have with social sharing and the OpenGraph system. For example, if you have only one\u00a0<code>index.html<\/code>\u00a0file to deliver to the client, they will only have one type of metadata\u2014most likely your homepage metadata. This won\u2019t be contextualized when you want to share a different route, so none of your routes will be shown on other sites with their proper user content (description and preview picture) that users would want to share with the world.<\/p>\r\n<h2 id=\"pre-rendering\">Pre-rendering<\/h2>\r\n<p>The mandatory server for a universal app can be a deterrent for some and may be overkill for a small application. This is why pre-rendering can be a really nice alternative.<\/p>\r\n<p>I discovered this solution with\u00a0<a href=\"https:\/\/blog.logrocket.com\/introduction-to-preact-a-smaller-faster-react-alternative-ad5532eb6d79\" rel=\"noopener noreferrer\">Preact<\/a>\u00a0and its own CLI that allows you to compile all pre-selected routes so you can store a fully populated HTML file to a\u00a0<em>static<\/em>\u00a0server. This lets you deliver a super-fast experience to the user, thanks to the Preact\/React hydration function, without the need for Node.js.<\/p>\r\n<p>The catch is, because this isn\u2019t SSR, you don\u2019t have user-specific data to show at this point\u2014it\u2019s just a static (and somewhat generic) file sent directly on the first request, as-is. So if you have user-specific data, here is where you can integrate a beautifully designed skeleton to show the user their data is coming, to avoid some frustration on their part:<\/p>\r\n<p>&nbsp;<\/p>\r\n<figure class=\"blog_post_image-container\"><img decoding=\"async\" class=\"deferred_image is-loaded\" src=\"https:\/\/uploads.toptal.io\/blog\/image\/127004\/toptal-blog-image-1535620212839-b5688b29b5058b9c9cf251284e7d0779.png\" alt=\"Using a document skeleton as part of a loading indicator\" \/><\/figure>\r\n<p>&nbsp;<\/p>\r\n<p>There is another catch: In order for this technique to work, you still need to have a proxy or something to redirect the user to the right file.<\/p>\r\n<h3 id=\"why\">Why?<\/h3>\r\n<p>With a single-page application, you need to redirect all requests to the root file, and then the framework redirects the user with its built-in routing system. So the first page load is always the same root file.<\/p>\r\n<p>In order for a pre-rendering solution to work, you need to tell your proxy that some routes need specific files and not always the root\u00a0<code>index.html<\/code>\u00a0file.<\/p>\r\n<p>For example, say you have four routes (<code>\/<\/code>,\u00a0<code>\/about<\/code>,\u00a0<code>\/jobs<\/code>, and\u00a0<code>blog<\/code>) and all of them have different layouts. You need four different HTML files to deliver the skeleton to the user that will then let\u00a0<a href=\"https:\/\/www.toptal.com\/react\">React<\/a>\/Preact\/etc. rehydrate it with data. So if you redirect all those routes to the root\u00a0<code>index.html<\/code>\u00a0file, the page will have an unpleasant, glitchy feel during loading, whereby the user will see the skeleton of the wrong page until it finishes loading and replaces the layout. For example, the user might see a homepage skeleton with only one column, when they had asked for a different page with a Pinterest-like gallery.<\/p>\r\n<p>The solution is to tell your proxy that each of those four routes needs a specific file:<\/p>\r\n<ul>\r\n<li><code>https:\/\/my-website.com<\/code>\u00a0\u2192 Redirect to the root\u00a0<code>index.html<\/code>\u00a0file<\/li>\r\n<li><code>https:\/\/my-website.com\/about<\/code>\u00a0\u2192 Redirect to the\u00a0<code>\/about\/index.html<\/code>\u00a0file<\/li>\r\n<li><code>https:\/\/my-website.com\/jobs<\/code>\u00a0\u2192 Redirect to the\u00a0<code>\/jobs\/index.html<\/code>\u00a0file<\/li>\r\n<li><code>https:\/\/my-website.com\/blog<\/code>\u00a0\u2192 Redirect to the\u00a0<code>\/blog\/index.html<\/code>\u00a0file<\/li>\r\n<\/ul>\r\n<p>This is why this solution can be useful for small applications\u2014you can see how painful it would be if you had a few hundred pages.<\/p>\r\n<p>Strictly speaking, it\u2019s not mandatory to do it this way\u2014you could just use a static file directly. For example,\u00a0<code>https:\/\/my-website.com\/about\/<\/code>\u00a0will work without any redirection because it will automatically search for an\u00a0<code>index.html<\/code>\u00a0inside its directory. But you need this proxy if you have param urls\u2014<code>https:\/\/my-website.com\/profile\/guillaume<\/code>\u00a0will need to redirect the request to\u00a0<code>\/profile\/index.html<\/code>\u00a0with its own layout, because\u00a0<code>profile\/guillaume\/index.html<\/code>\u00a0doesn\u2019t exist and will trigger a 404 error.<\/p>\r\n<p>&nbsp;<\/p>\r\n<figure class=\"blog_post_image-container\"><img decoding=\"async\" class=\"deferred_image is-loaded\" src=\"https:\/\/uploads.toptal.io\/blog\/image\/127005\/toptal-blog-image-1535714166711-83ff57e99f24e7b39e79cc0c766015ac.png\" alt=\"A flowchart showing how a proxy makes a difference in a pre-rendering solution, as described in the previous paragraph\" \/><\/figure>\r\n<p>&nbsp;<\/p>\r\n<hr \/>\r\n<p>In short, there are three basic views at play with the rendering strategies described above: A loading screen, a skeleton, and the full page once it\u2019s finally rendered.<\/p>\r\n<p>&nbsp;<\/p>\r\n<figure class=\"blog_post_image-container\"><img decoding=\"async\" class=\"deferred_image is-loaded\" src=\"https:\/\/uploads.toptal.io\/blog\/image\/126998\/toptal-blog-image-1535533781994-120b5191e09b6abe2e0cae668ffbe5d8.png\" alt=\"Comparing a loading screen, a skeleton, and a fully-rendered page\" \/><\/figure>\r\n<p>&nbsp;<\/p>\r\n<p>Depending on the strategy, sometimes we use all three of these views, and sometimes we jump straight to a fully-rendered page. Only in one use case are we forced to use a different approach:<\/p>\r\n<table>\r\n<thead>\r\n<tr>\r\n<th>Method<\/th>\r\n<th>Landing (e.g.\u00a0<code>\/<\/code>)<\/th>\r\n<th>Static (e.g.\u00a0<code>\/about<\/code>)<\/th>\r\n<th>Fixed Dynamic (e.g.\u00a0<code>\/news<\/code>)<\/th>\r\n<th>Parameterized Dynamic (e.g.\u00a0<code>\/users\/:user-id<\/code>)<\/th>\r\n<\/tr>\r\n<\/thead>\r\n<tbody>\r\n<tr>\r\n<td>Client-rendered<\/td>\r\n<td>Loading \u2192 Full<\/td>\r\n<td>Loading \u2192 Full<\/td>\r\n<td>Loading \u2192 Skeleton \u2192 Full<\/td>\r\n<td>Loading \u2192 Skeleton \u2192 Full<\/td>\r\n<\/tr>\r\n<tr>\r\n<td>Pre-rendered<\/td>\r\n<td>Full<\/td>\r\n<td>Full<\/td>\r\n<td>Skeleton \u2192 Full<\/td>\r\n<td>HTTP 404 (page not found)<\/td>\r\n<\/tr>\r\n<tr>\r\n<td>Pre-rendered With Proxy<\/td>\r\n<td>Full<\/td>\r\n<td>Full<\/td>\r\n<td>Skeleton \u2192 Full<\/td>\r\n<td>Skeleton \u2192 Full<\/td>\r\n<\/tr>\r\n<tr>\r\n<td>SSR<\/td>\r\n<td>Full<\/td>\r\n<td>Full<\/td>\r\n<td>Full<\/td>\r\n<td>Full<\/td>\r\n<\/tr>\r\n<\/tbody>\r\n<\/table>\r\n<h2 id=\"client-only-rendering-is-often-not-enough\">Client-only Rendering is Often Not Enough<\/h2>\r\n<p>Client-rendered applications are something we should avoid now because we can do better for the user. And doing better, in this case, is as easy as the pre-rendering solution. It\u2019s definitely an improvement over client-only rendering and easier to implement than a fully server-side-rendered application.<\/p>\r\n<p>An SSR\/universal application can be really powerful if you have a large application with a lot of different pages. It allows your content to be focused and relevant when talking to a social crawler. This is also true for search engine robots, which now take your site\u2019s performance into account when ranking it.<\/p>\r\n<p>Stay tuned for a follow-up tutorial, where I will walk through the transformation of an SPA into pre-rendered and SSR versions, and compare their performance.<\/p>\r\n<p>&nbsp;<\/p>\r\n","protected":false},"excerpt":{"rendered":"<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry&#8217;s standard dummy text ever since the 1500s.<\/p>\n","protected":false},"author":1,"featured_media":12,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"categories":[4],"tags":[9],"class_list":["post-25","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ip-address","tag-ipaddress"],"_links":{"self":[{"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/posts\/25","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/comments?post=25"}],"version-history":[{"count":3,"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/posts\/25\/revisions"}],"predecessor-version":[{"id":183,"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/posts\/25\/revisions\/183"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/media\/12"}],"wp:attachment":[{"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/media?parent=25"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/categories?post=25"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/techwyns.com\/tech\/wp-json\/wp\/v2\/tags?post=25"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}