<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: André Silva</title>
    <description>The latest articles on Forem by André Silva (@andresilva-cc).</description>
    <link>https://forem.com/andresilva-cc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1731411%2F47899b84-c337-40f4-af49-28c07c4514a4.jpg</url>
      <title>Forem: André Silva</title>
      <link>https://forem.com/andresilva-cc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andresilva-cc"/>
    <language>en</language>
    <item>
      <title>How I Achieved a 74% Performance Increase on a Page</title>
      <dc:creator>André Silva</dc:creator>
      <pubDate>Thu, 13 Feb 2025 21:06:31 +0000</pubDate>
      <link>https://forem.com/andresilva-cc/how-i-achieved-a-74-performance-increase-on-a-page-2gjm</link>
      <guid>https://forem.com/andresilva-cc/how-i-achieved-a-74-performance-increase-on-a-page-2gjm</guid>
      <description>&lt;h2&gt;
  
  
  Performance vs DX
&lt;/h2&gt;

&lt;p&gt;Atlas Technologies operates Brazil’s &lt;strong&gt;leading platform in its category&lt;/strong&gt;, with over 50 million monthly visits. Since most traffic comes from organic search, &lt;strong&gt;SEO and performance are critical&lt;/strong&gt;. Over the past few years, our team has grown rapidly, with over 200 people across technology and product. With this scale and our platform growing faster than ever, &lt;strong&gt;DX (Developer Experience) is really important&lt;/strong&gt;, thus being one of the responsibilities of the Platform Team that I'm part of.&lt;/p&gt;

&lt;p&gt;Our monolith is built with &lt;a href="https://laravel.com/" rel="noopener noreferrer"&gt;Laravel&lt;/a&gt; and &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt;, where Vue.js powers &lt;strong&gt;dynamic features at the expense of performance&lt;/strong&gt;, since it runs completely on the client-side. For performance-sensitive features, we rely on Blade (Laravel's template engine) with raw JavaScript or jQuery, &lt;strong&gt;resulting in a more complex and less developer-friendly approach&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adopting Nuxt
&lt;/h2&gt;

&lt;p&gt;A natural next step was adopting &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;, Vue.js’ meta-framework, which improves both DX and performance. We started by introducing Nuxt in less performance-sensitive areas, such as the user panel. As adoption grew, we eventually ended up with 3 Nuxt projects, each focused on specific sections of the product designed for logged-in users, where performance was less critical. The clear benefit was that developers enjoyed working with Nuxt due to its DX, &lt;strong&gt;enabling more dynamic features that are shipping faster&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;More recently, we finally decided to launch a new Nuxt project focused on public pages, ensuring strong performance without sacrificing DX. Since then, we've migrated several pages to this project, some of which saw an &lt;strong&gt;immediate performance boost simply by moving to Nuxt&lt;/strong&gt;, without major code changes. Of course, migration alone wasn't enough, we also had to &lt;strong&gt;dive deep into optimization&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring Performance
&lt;/h2&gt;

&lt;p&gt;We focused our efforts on a critical, content-heavy page that had one of the worst performance scores, an ideal candidate for improvement.&lt;/p&gt;

&lt;p&gt;But first, how do we reliably measure performance? This is a common challenge for anyone working with performance optimizations, and there are countless ways to do it. One obvious choice is &lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer"&gt;Google PageSpeed&lt;/a&gt;, which provides a &lt;strong&gt;Core Web Vitals&lt;/strong&gt; report when analyzing a page. Core Web Vitals offers highly reliable data since it's &lt;strong&gt;collected from real users&lt;/strong&gt;. However, changes take &lt;strong&gt;several days&lt;/strong&gt; &lt;strong&gt;to reflect&lt;/strong&gt; in the metrics, making it inefficient to measure your work.&lt;/p&gt;

&lt;p&gt;Below the Core Web Vitals panel, we have &lt;strong&gt;lab metrics&lt;/strong&gt;, which simulates a mobile device on a mobile connection. While less reliable than Core Web Vitals, lab metrics &lt;strong&gt;reflect changes instantly&lt;/strong&gt;. The downside is that results &lt;strong&gt;vary significantly between runs&lt;/strong&gt;, further reducing reliability.&lt;/p&gt;

&lt;p&gt;Still, I decided lab metrics could serve as a useful benchmark. To reduce the variability, I ran each test &lt;strong&gt;5 times and calculated the average&lt;/strong&gt;. The data was logged in a spreadsheet to track changes and assess how they impacted performance.&lt;/p&gt;

&lt;p&gt;While this method isn't perfect, it provided an easy and fairly reliable way to monitor progress. Before any improvements were made, PageSpeed reported the following averages:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;FCP (seconds)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;LCP (seconds)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;TBT (milliseconds)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;CLS&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Speed Index&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;37.60&lt;/td&gt;
&lt;td&gt;5.08&lt;/td&gt;
&lt;td&gt;8.42&lt;/td&gt;
&lt;td&gt;1108&lt;/td&gt;
&lt;td&gt;0.001&lt;/td&gt;
&lt;td&gt;6.76&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Optimizations
&lt;/h2&gt;

&lt;p&gt;I started by optimizing images with &lt;a href="https://image.nuxt.com/" rel="noopener noreferrer"&gt;Nuxt Image&lt;/a&gt;. Since we were already using &lt;a href="https://www.cloudflare.com/pt-br/lp/pg-images/" rel="noopener noreferrer"&gt;CloudFlare Images&lt;/a&gt; in other projects, setting up Nuxt Image was straightforward. For local development, I used UnJS's &lt;a href="https://github.com/unjs/ipx" rel="noopener noreferrer"&gt;IPX&lt;/a&gt; to avoid unnecessary CloudFlare costs. The provider alternates dynamically based on the environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APP_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloudflare&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ipx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I implemented &lt;strong&gt;lazy loading&lt;/strong&gt; for sections below the fold to reduce the initial load time. To achieve this, I created a utility function called &lt;code&gt;loadWhenVisible&lt;/code&gt;, which &lt;strong&gt;renders components only when they enter the viewport&lt;/strong&gt;. Until then, a placeholder is shown to indicate loading.&lt;/p&gt;

&lt;p&gt;However, this caused issues with anchor links when users navigated directly to a specific section. Since placeholders had fixed heights and section sizes were unknown in advance, scrolling sometimes landed in the wrong position. To improve this, I developed another utility function called &lt;code&gt;loadSequential&lt;/code&gt;, which &lt;strong&gt;loads sections one by one&lt;/strong&gt; instead of relying on visibility. This helped but didn't fully resolve all anchor issues. That's a topic for another article, but the most important here is that &lt;strong&gt;performance improved significantly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I also tested &lt;code&gt;nuxt-lcp-speedup&lt;/code&gt; (now called &lt;a href="https://github.com/johannschopplich/nuxt-vitalizer" rel="noopener noreferrer"&gt;Nuxt Vitalizer&lt;/a&gt;), which removes unnecessary prefetching of dynamic assets and eliminates some duplicate CSS, &lt;strong&gt;reducing LCP&lt;/strong&gt; (Largest Contentful Paint).&lt;/p&gt;

&lt;p&gt;Another discovery was a &lt;strong&gt;duplicated&lt;/strong&gt; &lt;code&gt;gtag&lt;/code&gt; script, which I removed to ensure it only loads once.&lt;/p&gt;

&lt;p&gt;Finally, I leveraged &lt;a href="https://nuxt.com/docs/guide/directory-structure/components#dynamic-imports" rel="noopener noreferrer"&gt;Nuxt's lazy loading for components&lt;/a&gt;. By prefixing component names with &lt;code&gt;Lazy&lt;/code&gt; and using &lt;code&gt;v-if&lt;/code&gt; conditions, I deferred loading of components that &lt;strong&gt;weren't needed immediately&lt;/strong&gt;. Since this feature requires &lt;a href="https://nuxt.com/docs/guide/concepts/auto-imports" rel="noopener noreferrer"&gt;Nuxt auto-imports&lt;/a&gt;, I refactored the entire project to enable auto-imports while ensuring no component names were duplicated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;All these optimizations led to the following results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;FCP (seconds)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;LCP (seconds)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;TBT (milliseconds)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;CLS&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Speed Index&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Before&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;37.60&lt;/td&gt;
&lt;td&gt;5.08&lt;/td&gt;
&lt;td&gt;8.42&lt;/td&gt;
&lt;td&gt;1108&lt;/td&gt;
&lt;td&gt;0.001&lt;/td&gt;
&lt;td&gt;6.76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;After&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;65.60&lt;/td&gt;
&lt;td&gt;2.50&lt;/td&gt;
&lt;td&gt;3.00&lt;/td&gt;
&lt;td&gt;1388&lt;/td&gt;
&lt;td&gt;0.001&lt;/td&gt;
&lt;td&gt;3.04&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Difference&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;+28.00&lt;/td&gt;
&lt;td&gt;-2.58&lt;/td&gt;
&lt;td&gt;-5.42&lt;/td&gt;
&lt;td&gt;+280&lt;/td&gt;
&lt;td&gt;0.000&lt;/td&gt;
&lt;td&gt;-3.72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Difference (%)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;+74.47%&lt;/td&gt;
&lt;td&gt;-50.79%&lt;/td&gt;
&lt;td&gt;-64.37%&lt;/td&gt;
&lt;td&gt;+25,27%&lt;/td&gt;
&lt;td&gt;0.00%&lt;/td&gt;
&lt;td&gt;-55.03%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We saw a &lt;strong&gt;significant improvement&lt;/strong&gt; in the overall performance score, as well as in FCP, LCP, and Speed Index. However, TBT (Total Blocking Time) increased, though it's hard to draw conclusions from it. Among all the metrics, TBT had the &lt;strong&gt;highest variability&lt;/strong&gt;, sometimes fluctuating between 500ms and 2000ms. 5 test runs may not have been enough to smooth out these variations.&lt;/p&gt;

&lt;p&gt;It's also worth noting that &lt;strong&gt;other teams were making changes to the same page during this period&lt;/strong&gt;, which may have influenced the final metrics. Still, the results clearly show that the effort was worthwhile.&lt;/p&gt;

&lt;p&gt;There's still room for further optimization, but most of it would involve fine-tuning and content-related adjustments. With our main objectives achieved, we considered this phase of the work complete, leaving future improvements to other teams.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>nuxt</category>
      <category>webperf</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Rendering Modes Explained</title>
      <dc:creator>André Silva</dc:creator>
      <pubDate>Wed, 10 Jul 2024 14:02:04 +0000</pubDate>
      <link>https://forem.com/andresilva-cc/rendering-modes-explained-2711</link>
      <guid>https://forem.com/andresilva-cc/rendering-modes-explained-2711</guid>
      <description>&lt;p&gt;In this article, we will explore the different &lt;strong&gt;rendering modes&lt;/strong&gt; for a web application, commonly seen in meta-frameworks like &lt;strong&gt;Next.js&lt;/strong&gt; and &lt;strong&gt;Nuxt&lt;/strong&gt;. Understanding these modes is &lt;strong&gt;crucial&lt;/strong&gt; for developers seeking to &lt;strong&gt;optimize performance&lt;/strong&gt; and &lt;strong&gt;user experience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For demonstration purposes, we will use a project I've developed in Nuxt 3, which makes it easier to see the differences between the rendering modes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Client-Side Rendering (CSR)
&lt;/h2&gt;

&lt;p&gt;Modern JavaScript libraries and frameworks like &lt;strong&gt;Vue.js&lt;/strong&gt; and &lt;strong&gt;React.js&lt;/strong&gt; brought many improvements to the front-end ecosystem, such as &lt;strong&gt;easier componentization&lt;/strong&gt; and a &lt;strong&gt;reactivity system&lt;/strong&gt;, but they also introduced their own challenges.&lt;/p&gt;

&lt;p&gt;When we talk about &lt;strong&gt;Client-Side Rendering&lt;/strong&gt; &lt;strong&gt;(CSR)&lt;/strong&gt;, it's how those frameworks typically operate &lt;strong&gt;by default&lt;/strong&gt;. Rendering occurs entirely on the &lt;strong&gt;client-side&lt;/strong&gt;, within the browser. This means that the server delivers a &lt;strong&gt;blank page&lt;/strong&gt; and then the &lt;strong&gt;JavaScript&lt;/strong&gt; needs to be downloaded and executed to &lt;strong&gt;render the UI&lt;/strong&gt; to the user. Consequently, there's a period during which the user sees &lt;strong&gt;no content&lt;/strong&gt;, which can vary based on the user's network speed and hardware.&lt;/p&gt;

&lt;p&gt;In addition to the &lt;strong&gt;poor user experience&lt;/strong&gt; inherent in this rendering mode, &lt;strong&gt;SEO&lt;/strong&gt; is also impacted because web crawlers must &lt;strong&gt;wait for the page to be fully rendered&lt;/strong&gt; before they can index it.&lt;/p&gt;

&lt;p&gt;This mode is also commonly referred to as &lt;strong&gt;SPA (Single Page Application)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9bb37bokj76v3hkzxjx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9bb37bokj76v3hkzxjx.png" alt="Client-Side Rendering" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lesser complexity&lt;/li&gt;
&lt;li&gt;Can be hosted on a static server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blank page while JavaScript is not executed&lt;/li&gt;
&lt;li&gt;Bad for SEO&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Demonstration
&lt;/h3&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/wYogjDe9YoA"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Server-Side Rendering (SSR)
&lt;/h2&gt;

&lt;p&gt;The meta-frameworks were created to mainly solve that problem. When we talk about “meta-framework”, it usually means a framework that is built on top of another, providing further abstraction and tools. For example, &lt;strong&gt;Next.js&lt;/strong&gt; is a meta-framework for &lt;strong&gt;React.js&lt;/strong&gt; and &lt;strong&gt;Nuxt&lt;/strong&gt; is a meta-framework for &lt;strong&gt;Vue.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;How they solve that problem is by introducing &lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt;. When the browser requests a page from the server, instead of the server responding with a &lt;strong&gt;blank page&lt;/strong&gt;, it runs the framework on the &lt;strong&gt;server-side&lt;/strong&gt; to &lt;strong&gt;render the page&lt;/strong&gt;. This means that the user doesn't see a blank page anymore, but a &lt;strong&gt;fully-rendered page&lt;/strong&gt; without executing any JavaScript on the browser.&lt;/p&gt;

&lt;p&gt;Of course, that page is completely static, so there's &lt;strong&gt;no interactivity&lt;/strong&gt;. The process of turning the static page into an interactive page is called &lt;strong&gt;hydration&lt;/strong&gt;. Basically, what this means is that the framework is run again on the browser side, so it &lt;strong&gt;binds all the&lt;/strong&gt; &lt;strong&gt;event listeners&lt;/strong&gt; in the DOM and makes the page &lt;strong&gt;interactive&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An important point to understand is that usually, our &lt;strong&gt;API calls&lt;/strong&gt; need to be made on the &lt;strong&gt;server&lt;/strong&gt; so that the data is present to &lt;strong&gt;render the page&lt;/strong&gt;. The meta-frameworks usually introduce some sort of &lt;strong&gt;hook or function&lt;/strong&gt; that makes all those requests run on the server and not be duplicated in the client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1g5f0r7wiinxceawg9a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1g5f0r7wiinxceawg9a.png" alt="Server-Side Rendering" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Good for SEO&lt;/li&gt;
&lt;li&gt;Page content available immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Greater complexity&lt;/li&gt;
&lt;li&gt;Needs a server with support&lt;/li&gt;
&lt;li&gt;Bigger processing cost&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Demonstration
&lt;/h3&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/KrMVfwJ9MfM"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Static Site Generation (SSG)
&lt;/h2&gt;

&lt;p&gt;Another feature that the meta-frameworks introduced is &lt;strong&gt;Static Site Generation (SSG)&lt;/strong&gt;. &lt;strong&gt;Static&lt;/strong&gt; means that the page doesn't depend on any dynamic data.&lt;/p&gt;

&lt;p&gt;For example, imagine a &lt;strong&gt;profile page&lt;/strong&gt;. A profile page should not be static because the content of the page is different based on the user details. On the other hand, a page that describes the &lt;strong&gt;terms and conditions&lt;/strong&gt; of your application is always going to be the same, because it doesn't have any dynamic data that needs to be fetched on the server-side.&lt;/p&gt;

&lt;p&gt;For those cases, it's a good option to opt for &lt;strong&gt;SSG&lt;/strong&gt;. Those pages are going to be &lt;strong&gt;rendered at&lt;/strong&gt; &lt;strong&gt;build time&lt;/strong&gt; and will not change, so the server uses &lt;strong&gt;fewer resources&lt;/strong&gt; to deliver those pages to the client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0a8qbc8bhe41rvr653bo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0a8qbc8bhe41rvr653bo.png" alt="Static Site Generation" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Good for SEO&lt;/li&gt;
&lt;li&gt;Page content available immediately&lt;/li&gt;
&lt;li&gt;Can be hosted on a static server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Greater complexity&lt;/li&gt;
&lt;li&gt;Limitation with dynamic route parameters&lt;/li&gt;
&lt;li&gt;Dynamic content not updated after build&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Demonstration
&lt;/h3&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Uh7mBQL0FIE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Incremental Static Regeneration (ISR)
&lt;/h2&gt;

&lt;p&gt;The last option and the most recent one introduced by meta-frameworks is &lt;strong&gt;Incremental Static Regeneration (ISR)&lt;/strong&gt;. One easy way to describe it is that it is a mix of &lt;strong&gt;SSR&lt;/strong&gt; and &lt;strong&gt;SSG&lt;/strong&gt; because it &lt;strong&gt;renders the page&lt;/strong&gt;, &lt;strong&gt;caches it&lt;/strong&gt;, and &lt;strong&gt;revalidates it&lt;/strong&gt; after a specific time interval.&lt;/p&gt;

&lt;p&gt;For example, imagine a page with the most recent blog posts. New posts aren't created every second, so it makes sense to &lt;strong&gt;render the page&lt;/strong&gt;, &lt;strong&gt;cache it&lt;/strong&gt;, and after 1 minute &lt;strong&gt;re-render the page&lt;/strong&gt;. While the &lt;strong&gt;TTL (Time To Live)&lt;/strong&gt; doesn't expire, the server will deliver the cached page.&lt;/p&gt;

&lt;p&gt;When using &lt;strong&gt;ISR&lt;/strong&gt;, it's up to you to define the TTL of the page, so choose a setting that makes sense for the page in question.&lt;/p&gt;

&lt;p&gt;Other terms that may be used are: &lt;strong&gt;Incremental Static Generation (ISG)&lt;/strong&gt; and &lt;strong&gt;Stale-While-Revalidate (SWR)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8eez42ed2hiolnapedg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8eez42ed2hiolnapedg.png" alt="Incremental Static Regeneration" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Good for SEO&lt;/li&gt;
&lt;li&gt;Page content available immediately&lt;/li&gt;
&lt;li&gt;Smaller processing cost when compared to SSR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Greater complexity&lt;/li&gt;
&lt;li&gt;Needs a server with support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Demonstration
&lt;/h3&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/iNC9fqek8wk"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Project
&lt;/h2&gt;

&lt;p&gt;As I've mentioned at the beginning of the article, this is the project I've used to demonstrate the rendering modes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Website:&lt;/strong&gt; &lt;a href="https://renderingmodes.andresilva.cc/" rel="noopener noreferrer"&gt;https://renderingmodes.andresilva.cc/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/andresilva-cc/demo-nuxt3-rendering-modes" rel="noopener noreferrer"&gt;https://github.com/andresilva-cc/demo-nuxt3-rendering-modes&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
