<?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>DEV Community: ellioseven</title>
    <description>The latest articles on DEV Community by ellioseven (@ellioseven).</description>
    <link>https://dev.to/ellioseven</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%2F490207%2Fc8d86d33-726a-4b74-8343-a4d7f0e3b2cc.jpeg</url>
      <title>DEV Community: ellioseven</title>
      <link>https://dev.to/ellioseven</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ellioseven"/>
    <language>en</language>
    <item>
      <title>A Next.js + Firebase TDD Environment Example</title>
      <dc:creator>ellioseven</dc:creator>
      <pubDate>Fri, 09 Apr 2021 05:30:04 +0000</pubDate>
      <link>https://dev.to/ellioseven/a-next-js-firebase-tdd-environment-example-3ojp</link>
      <guid>https://dev.to/ellioseven/a-next-js-firebase-tdd-environment-example-3ojp</guid>
      <description>&lt;p&gt;Recently I've been working with a start-up that leverages Next.js and Firebase. This is a very interesting stack, as it lends itself to a very fast development lifecycle. As a result, it's been tempting to let testing take a back seat, especially when the initial development cost for a testing environment with a range of testing strategies is quite large.&lt;/p&gt;

&lt;p&gt;I've spent some time creating a TDD environment for a Next.js and Firebase application, so I thought I'd share my results here to reduce that time cost and help avoid some of the confusion and traps.&lt;/p&gt;

&lt;p&gt;The rest of the article outlines a basic overview, features, technologies used, architecture notes and strategies covered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ellioseven/next-firebase-testing"&gt;Check out the code&lt;/a&gt;, illustrating how I've created the environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The repo contains a simple application that allows a user to enter a score, which may appear on the top score board. The application attempts to include a surface area of functionality you'd find in a typical Next.js application. See the &lt;a href="https://github.com/ellioseven/next-firebase-testing/blob/master/README.md"&gt;README&lt;/a&gt; for instructions how to install and run the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Emulated Firebase: Firebase offers local emulated environments, including Firestore and Functions&lt;/li&gt;
&lt;li&gt;Component Tests: Simple tests with RWT&lt;/li&gt;
&lt;li&gt;API Integration Tests: API endpoint tests that verify Firestore data&lt;/li&gt;
&lt;li&gt;Firestore Functions Unit Tests: Tests that consume and verify emulated Firestore Function logic&lt;/li&gt;
&lt;li&gt;Application E2E Tests: End to end tests with Cypress.js&lt;/li&gt;
&lt;li&gt;CircleCI Integration: A simple example showcasing how to set up tests suites into a CI pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Technologies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker: Virtualised environments for application &amp;amp; Firebase runtimes&lt;/li&gt;
&lt;li&gt;Next.js: Popular React application runtime&lt;/li&gt;
&lt;li&gt;Firebase: Popular database and serverless function infrastructure&lt;/li&gt;
&lt;li&gt;Cypress: Automated browser simulation for integration tests&lt;/li&gt;
&lt;li&gt;Jest: Automated testing framework&lt;/li&gt;
&lt;li&gt;React Testing Library: Automated React testing library&lt;/li&gt;
&lt;li&gt;MSW: API mocking library&lt;/li&gt;
&lt;li&gt;CircleCI: Continuous integration &amp;amp; delivery SaaS&lt;/li&gt;
&lt;li&gt;Husky: Bootstrap local development with Git hooks to run tests on Git events&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.circleci&lt;/code&gt; - CircleCI configuration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.docker&lt;/code&gt; - Docker configuration and storage for images&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cypress&lt;/code&gt; - Cypress E2E configuration and assertions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;packages/app&lt;/code&gt; - Next.js application&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;packages/firebase&lt;/code&gt; - Firebase services and Firestore data collections&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;packages/functions&lt;/code&gt; - Firebase Functions logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing Architecture
&lt;/h2&gt;

&lt;p&gt;The goal is to create an environment that solves complexities for test strategies, so that any area in the stack can be covered by a test, breadth over depth. This helps developers figure out "how" to create tests.&lt;/p&gt;

&lt;p&gt;Docker is used to make it as easy as a simple command to build all the system dependencies, such as Node, Cypress, Java, Firebase CI and emulators, etc. This makes it extremely easy to pull down and configure the testing environment. The are two environments, &lt;code&gt;dev&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt;, which provide the different services and configuration required.&lt;/p&gt;

&lt;p&gt;During local development, seed data is injected to create a controllable and reliable test data for tests and local development. When the application boots, a history of scores and a leaderboard is already created. This provides consistent data across the development and testing team. This is done in a Docker service, which will wait for the Firebase emulators to become healthy before migration.&lt;/p&gt;

&lt;p&gt;Firebase provides emulators that mimic some of their cloud services such as Firestore and Functions. This is extremely helpful, but getting the environment set up can be confusing and time confusing (system dependencies, environment variables, configuration, etc.). Grokking how to test assert Firestore data and test serverless functions can be difficult. This repository attempts to help solve that.&lt;/p&gt;

&lt;p&gt;I've also included CircleCI integration to show how the test environment can be built in a CI process. I use the &lt;a href="https://circleci.com/docs/2.0/executor-types/#using-machine"&gt;machine type executor&lt;/a&gt; which provides a VM with full network management and Docker utilities. This makes it easy to use Docker's "host network mode", which simplifies container networking.&lt;/p&gt;

&lt;p&gt;Mono-repositories are a popular pattern, so I have implemented this approach with &lt;a href="https://github.com/lerna/lerna"&gt;Lerna&lt;/a&gt; to show how the structure might look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Strategies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React Unit Tests
&lt;/h3&gt;

&lt;p&gt;There is a huge amount of resources on how to run unit tests against React components, and so isn't the focus of this repository. I have included some basic Next.js/React tests that assert component and API interaction to depict how they can be structured.&lt;/p&gt;

&lt;h3&gt;
  
  
  API/Firebase Integration Tests
&lt;/h3&gt;

&lt;p&gt;Examples include how to pre-populate and tear down the emulated Firebase environment for each API integration test. Be aware that Firestore interaction (eg: pre-populating data) will trigger built Firebase functions. If possible, it's best to keep interaction to a minimum to prevent a high frequency of triggers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firebase Functions Tests
&lt;/h3&gt;

&lt;p&gt;Firebase comes with testing libraries which help interact with emulated environments. I've included some examples that pre-populate Firestore and run simulated snapshots. Testing functions can be tricky, as they run as synchronous background tasks, meaning they can't be simply changed and asserted. This can also cause potential race conditions. To overcome this problem, I've provided a simple solution that waits and retries for the assertion.&lt;/p&gt;

&lt;h3&gt;
  
  
  E2E Tests
&lt;/h3&gt;

&lt;p&gt;End to end tests are managed with Cypress. Before Cypress can be launched, packages are built, the emulators are run, data is seeded, then the Next.js is booted in production mode. This prevents any problems with having to wait for pages to compile, which can cause timeout issues. The timing sequence is managed by Docker Compose, which will check for healthy services before running appropriate tasks.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>firebase</category>
      <category>testing</category>
      <category>react</category>
    </item>
    <item>
      <title>A Next.js Application Retrospective</title>
      <dc:creator>ellioseven</dc:creator>
      <pubDate>Sun, 18 Oct 2020 00:55:23 +0000</pubDate>
      <link>https://dev.to/ellioseven/a-next-js-application-retrospective-400m</link>
      <guid>https://dev.to/ellioseven/a-next-js-application-retrospective-400m</guid>
      <description>&lt;p&gt;I've spent the last couple of years developing an SSR application with Next.js and Apollo. The project features a mixture of job boards, a large amount of content (from a CMS) and user profiles. I thought I'd share some of the challenges, mistakes and thing's I wish I knew before I started.&lt;/p&gt;

&lt;p&gt;Some of these to you might be quite obvious, however what I listed here was really important to the success of our project. Hopefully it will be of use to some.&lt;/p&gt;

&lt;h1&gt;
  
  
  tldr;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Do you really need to SSR?&lt;/li&gt;
&lt;li&gt;Monitor Performance Early&lt;/li&gt;
&lt;li&gt;getInitialProps Optimisation is Vital&lt;/li&gt;
&lt;li&gt;Apollo Cache Key Optimisation is Vital&lt;/li&gt;
&lt;li&gt;Watch Out for Styled Component Nested Props&lt;/li&gt;
&lt;li&gt;async/await in getInitialProps&lt;/li&gt;
&lt;li&gt;Consider Building a Version Notification System Early On&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Do you really need to SSR?
&lt;/h1&gt;

&lt;p&gt;The first hurdle was determining if we really needed server side rendering. Obviously there are many pros and cons to analyse. It's really important to weigh these options and understand the trade-offs between a static, dynamic or server side build.&lt;/p&gt;

&lt;p&gt;For us, SEO was a determining factor. We needed to display source HTML for search engines, as well as managing meta and redirects. Alternative methods, such as pre-generated content just wasn't viable, as we had huge amounts of multi-tenant content that's published and changed frequently.&lt;/p&gt;

&lt;p&gt;You should ask yourself if the benefits of SSR (eg: SEO, request/response control) outweigh the cons (eg: time to first byte, complexity, server infrastructure).&lt;/p&gt;

&lt;p&gt;As a general guideline, I try to favour static generated sites for performance reasons. Study &lt;a href="https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation"&gt;&lt;code&gt;getStaticPaths&lt;/code&gt;&lt;/a&gt; to see if it can work for you.&lt;/p&gt;

&lt;h1&gt;
  
  
  Monitor Performance Early
&lt;/h1&gt;

&lt;p&gt;This aspect is not tied to SSR rendering, but an important fundamental. It's too easy to make a decision and be completely unaware that you've made a huge impact on performance.&lt;/p&gt;

&lt;p&gt;For example, you've got a requirement that needs to support timezones. You use moment.js, build your feature, test it, deploy it. Boom. Easy. However, you didn't realise that you accidentally used all locales, which means 4MB of uncompressed JSON is now being distributed to your users.&lt;/p&gt;

&lt;p&gt;This mistake may be obvious to you, but maybe not to a team member.&lt;/p&gt;

&lt;p&gt;So many mistakes could of been prevented by implementing a &lt;a href="https://www.thoughtworks.com/radar/techniques/architectural-fitness-function"&gt;fitness function&lt;/a&gt; that analyses performance as part of the CI pipeline. Automatic budgets on time to first byte, bundle size and HTML page size are &lt;strong&gt;really important to prevent performance blunders being deployed to production&lt;/strong&gt;. Use something like &lt;a href="https://github.com/GoogleChrome/lighthouse-ci"&gt;Google Lighthouse&lt;/a&gt; to track those metrics.&lt;/p&gt;

&lt;p&gt;This optimisation will help find many problems mentioned later in this article.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;getInitialProps&lt;/code&gt; Optimisation is Vital
&lt;/h1&gt;

&lt;p&gt;Everything that you pass from &lt;code&gt;getInitialProps&lt;/code&gt; gets hydrated. It's &lt;strong&gt;printed&lt;/strong&gt; directly to HTML, which means the user has to retrieve and parse it first &lt;strong&gt;before anything else can happen&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Always keep this is the back of your head. &lt;strong&gt;Do you need that data?&lt;/strong&gt; It's very easy to pass a large amount of data that isn't used, forcing users to download and wait for a whole bunch of data they don't need.&lt;/p&gt;

&lt;p&gt;This is something that should be tracked in the CI pipeline.&lt;/p&gt;

&lt;h1&gt;
  
  
  Apollo Cache Key Optimisation is Vital
&lt;/h1&gt;

&lt;p&gt;When using Apollo, you should have a basic awareness on &lt;a href="https://www.apollographql.com/docs/react/caching/cache-configuration/#data-normalization"&gt;how normalisation works&lt;/a&gt;. Apollo will attempt to break up and normalise objects on a type and ID. Failing that, it will attempt to store the object based on how it's queried.&lt;/p&gt;

&lt;p&gt;Apollo will try to pass the cache during the hydration process, by &lt;strong&gt;printing it to HTML&lt;/strong&gt;. This is a huge optimisation opportunity for SSR. Without effectively normalised data, the HTML size can really grow quickly.&lt;/p&gt;

&lt;p&gt;A lot of our content uses an &lt;code&gt;entityId&lt;/code&gt; unique identifier, instead of the default &lt;code&gt;_id&lt;/code&gt; or &lt;code&gt;id&lt;/code&gt; identifier. The cache passed via HTML was huge in some cases. By &lt;a href="https://www.apollographql.com/docs/react/caching/cache-configuration/#customizing-identifier-generation-by-type"&gt;implementing a cache key&lt;/a&gt;, large amounts of raw HTML was trimmed.&lt;/p&gt;

&lt;p&gt;This is something that should be tracked in the CI pipeline.&lt;/p&gt;

&lt;h1&gt;
  
  
  Watch Out for Styled Component Nested Props
&lt;/h1&gt;

&lt;p&gt;When using styled components, you can pass dynamic props to a component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="s2"&gt;`
  border: 1px solid blue;

  .title {
    color: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
  }
`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Card&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feature is powerful, however because the prop is on a nested selector, this caused &lt;strong&gt;large amounts of duplicated styles to be printed directly to HTML&lt;/strong&gt;, which again, forced users to download and wait for data they didn't need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be very vary of using props on nested styles&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This can be resolved by using an additional styled component:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Title&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Card&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Title&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or by using plain old CSS (my preferred approach):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="nt"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"title"&lt;/span&gt; &lt;span class="nt"&gt;data-color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"blue"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;Card&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;code&gt;async/await&lt;/code&gt; in &lt;code&gt;getInitialProps&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Using &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; in &lt;code&gt;getInitialProps&lt;/code&gt; will block the entire request until the response has been resolved.&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;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avoid doing this as much as you can, be &lt;strong&gt;aware of the cost&lt;/strong&gt;. Every millisecond waiting for that response will an extra millisecond on the time to first byte.&lt;/p&gt;

&lt;h1&gt;
  
  
  Consider Building a Version Notification System Early On
&lt;/h1&gt;

&lt;p&gt;So any headaches were caused because a lot of user's &lt;strong&gt;leave tabs open&lt;/strong&gt; and &lt;strong&gt;do not refresh the page&lt;/strong&gt;. The Next.js application is cached in memory over client side navigation, and may not receive a new version until the page has been refreshed. If your application communicates with an API, this situation gets complicated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;A new version of the CMS removes a data type from the content API, which the frontend relies on. The change gets deployed on both platforms. However, the user has the original version in the browser. They navigate to a page that relies on that now removed data type, theres an error.&lt;/p&gt;

&lt;p&gt;Yes, there are many ways to handle this error and could be alleviated with API versioning. However, the problem is complex, you may easily find yourself fall into this trap accidentally.&lt;/p&gt;

&lt;p&gt;It may not be immediately obvious to the user that they need to refresh, &lt;strong&gt;especially if the error is silent&lt;/strong&gt;. The situation becomes worse if that request is critical, such as authentication.&lt;/p&gt;

&lt;p&gt;Notifying users that a new version is available can really help improve the situation. This solution may not be for you, but a notification system is a simplistic implementation that can help drastically.&lt;/p&gt;

&lt;h1&gt;
  
  
  That's All
&lt;/h1&gt;

&lt;p&gt;If you got this far, thanks for taking the time to read my first published article. Hopefully this helps some avoid the traps and pitfalls made.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
