<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>Tim&#39;s Tech Blog</title>
	<subtitle>I write about Web Development, Web Performance, Web Security, JavaScript, TypeScript, React.</subtitle>
	
	<link href="https://timtech.blog/feed/feed.xml" rel="self"/>
	<link href="https://timtech.blog/"/>
	<updated>2023-11-07T00:00:00+00:00</updated>
	<id>https://timtech.blog/</id>
	<author>
		<name>Timothée “Tim” Pillard</name>
		<email>tim@timtech.blog</email>
	</author>
	
	<entry>
		<title>React Server Components, without a framework?</title>
		<link href="https://timtech.blog/posts/react-server-components-rsc-no-framework/"/>
		<updated>2023-11-07T00:00:00+00:00</updated>
		<id>https://timtech.blog/posts/react-server-components-rsc-no-framework/</id>
		<content type="html">&lt;img src=&quot;https://timtech.blog/img/react-server-components-rsc-no-framework-demo-screenshot.webp&quot; alt=&quot;Screenshot of the RSC Notes App Demo / Playground&quot; width=&quot;800&quot; style=&quot;border: 1px solid #282c34;&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://rsc-demo.timtech.blog/&quot;&gt;Live RSC Notes App Demo / Playground&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ziir/rsc-demo&quot;&gt;Source code on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;direct-link&quot; href=&quot;#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;React Server&lt;/strong&gt; features, concepts &amp;amp; APIs, in particular &lt;strong&gt;React Server Components&lt;/strong&gt; &amp;amp; &lt;strong&gt;React Server Actions&lt;/strong&gt; have been in the spotlight for the past week, following recent announcements by the React Team (&lt;a href=&quot;https://twitter.com/reactjs/status/1716573234160967762&quot;&gt;&lt;strong&gt;React Server &amp;amp; Client Actions&lt;/strong&gt; on October 23rd&lt;/a&gt;) &amp;amp; Next.js - &lt;strong&gt;Next.js 14 “Server Actions (stable)”&lt;/strong&gt; announced on &lt;a href=&quot;https://twitter.com/nextjs/status/1717596665690091542&quot;&gt;October 26th 2023&lt;/a&gt; at Next.js Conf - which had a very strong &lt;em&gt;resonance&lt;/em&gt; in tech communities &amp;amp; on social media.&lt;/p&gt;
&lt;p&gt;Before then, I was somewhat oblivious to the &lt;abbr title=&quot;React Server Components&quot;&gt;RSC&lt;/abbr&gt; model, and upcoming &lt;a href=&quot;https://react.dev/community/versioning-policy#canary-channel&quot;&gt;React Canary&lt;/a&gt; features.&lt;/p&gt;
&lt;p&gt;Sure, over the years, I had heard &amp;amp; thought quite a bit about the possibilities of a React putting a stronger focus on the server, especially when I was working at &lt;em&gt;Gandi&lt;/em&gt; for 6 years, where we had been working with React since &lt;code&gt;~v0.13.0 / 2015&lt;/code&gt;, building our own, in-house, custom &lt;strong&gt;&lt;em&gt;React / Redux isomorphic / universal SPA / SSR full-stack framework&lt;/em&gt;&lt;/strong&gt;, architecture &amp;amp; ecosystem powering ~10 business-critical production applications.&lt;br&gt;
I had also dipped a toe in the &lt;a href=&quot;https://github.com/mozilla/addons-frontend&quot;&gt;mozilla/addons-frontend&lt;/a&gt; code base of &lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;Mozilla Addons marketplace (AMO)&lt;/a&gt;, which leverages a comparable architecture, from the same &lt;em&gt;era&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Despite the years, the distance &amp;amp; perspective I now have from my old job at Gandi (I left in 2020 after 6years), the technical challenges related to my experience, striving to build a performant, resilient, capable, productive, tailored, in-house &lt;strong&gt;React framework&lt;/strong&gt; with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement&quot;&gt;progressive enhancement&lt;/a&gt; and &lt;code&gt;no-js&lt;/code&gt; first-class support (essentially what &lt;strong&gt;meta-frameworks&lt;/strong&gt; such as &lt;a href=&quot;https://remix.run/&quot;&gt;Remix&lt;/a&gt;, &lt;em&gt;Next.js&lt;/em&gt; &amp;amp; maybe others &lt;strong&gt;&lt;em&gt;can&lt;/em&gt;&lt;/strong&gt; do &lt;strong&gt;today&lt;/strong&gt; if you&#39;re &lt;strong&gt;serious&lt;/strong&gt; about it), have been living rent-free in my head ever since (and I have many more like that, such as &lt;a href=&quot;https://timtech.blog/posts/react-memo-is-good-actually/&quot;&gt;when to use React.memo&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;So of course, when I saw on Twitter the &lt;a href=&quot;#introduction&quot;&gt;RSC / React Canary / Server &amp;amp; Client Actions announcements&lt;/a&gt; mentioned earlier, I was excited!&lt;br&gt;
Could it be? A &lt;em&gt;React-native&lt;/em&gt;, official first-party solution to all the &lt;em&gt;problems of React server-side rendering&lt;/em&gt;: data-fetching, waterfall, routing, latency, partial / selective hydration, in-or-out-of-order streaming, you name it: &lt;strong&gt;maybe that was it&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And so, I began an unreasonable journey, starting to look into &lt;strong&gt;React Server APIs&lt;/strong&gt;, the &lt;strong&gt;RSC model&lt;/strong&gt;, &lt;strong&gt;Client / Server actions&lt;/strong&gt;, &lt;strong&gt;React Canary&lt;/strong&gt;, etc. from scratch, with close to zero prior knowledge, and a lot of interrogations.&lt;/p&gt;
&lt;h2 id=&quot;rsc-survival-guide&quot;&gt;RSC Survival Guide &lt;a class=&quot;direct-link&quot; href=&quot;#rsc-survival-guide&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before going any further, chances are the average reader is as confused about all this as I was when I first started looking into this a few days ago.&lt;br&gt;
Indeed, &lt;em&gt;X dot com&lt;/em&gt; is full of keywords, code snippets, memes &amp;amp; engagement baits while actual information regarding this topic is scattered, incomplete, missing, tied to a specific Meta-framework, focused on high level use cases, or simply slightly harder to find than the typical React content covering mature &amp;amp; stable patterns, such as &lt;a href=&quot;https://timtech.blog/posts/presentation-dashlane-react-form-handling-giving-up-control-example-controlled-input/&quot;&gt;React controlled inputs&lt;/a&gt; - ok that&#39;s the last internal backlink, I &lt;a href=&quot;https://timtech.blog/posts/limiting-async-operations-promise-concurrency-javascript/&quot;&gt;Promise concurrently&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;disclaimer&quot;&gt;Disclaimer &lt;a class=&quot;direct-link&quot; href=&quot;#disclaimer&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This section aims to serve as a &lt;strong&gt;quick reference&lt;/strong&gt; for &lt;strong&gt;&lt;abbr title=&quot;React Server Components&quot;&gt;RSC&lt;/abbr&gt;&lt;/strong&gt;, centralizing what I consider to be the most important terms, definitions &amp;amp; concepts about these features, just so a maximum amount of readers who made it this far (thank you! means a lot to me) can follow along with the rest of the blog post.&lt;/p&gt;
&lt;p&gt;The goal is not to provide a guide on how to use these features, rather an extract &amp;amp; structuring of my personal understanding of the different pieces of the puzzle based on my personal research, with links to relevant resources.&lt;/p&gt;
&lt;p&gt;Please bear in mind this blog post mentions &lt;strong&gt;experimental &amp;amp; under-documented features &amp;amp; APIs&lt;/strong&gt; and generally covers a &lt;strong&gt;complex &amp;amp; continously-evolving topic&lt;/strong&gt; - it may not be the best source of information for beginners or readers who have never yet been exposed to the concepts of the RSC Model.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;THE BLOG POST IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED…&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;react-client-components&quot;&gt;React Client Components &lt;a class=&quot;direct-link&quot; href=&quot;#react-client-components&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;React Client Components&lt;/strong&gt; are traditional React Components - which &lt;strong&gt;can run on the client&lt;/strong&gt;, traditionally the browser.&lt;br&gt;
Chances are, most of the React components you&#39;ve ever been in contact with and that you&#39;re used to, at least prior to &lt;a href=&quot;https://react.dev/blog/2022/03/29/react-v18&quot;&gt;React 18&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://nextjs.org/blog/next-13&quot;&gt;Next.js 13&lt;/a&gt; were Client Components, and this, regardless of them being rendered by &lt;a href=&quot;https://react.dev/reference/react-dom/server&quot;&gt;React DOM Server APIs&lt;/a&gt; to produce or stream &lt;abbr title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/abbr&gt; for &lt;em&gt;server-side rendering (SSR)&lt;/em&gt; or &lt;em&gt;build-time static site generation (SSG)&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“The name “Client Component” doesn’t mean anything new, it only serves to distinguish these components from Server Components”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“If you have an existing client-side app, you can think of all of it as a Client Component tree”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/reactjs/rfcs/pull/188&quot;&gt;RFC: React Server Components #188&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-react-server-components-model&quot;&gt;The React Server Components Model &lt;a class=&quot;direct-link&quot; href=&quot;#the-react-server-components-model&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;react-server-components-announcements-timeline&quot;&gt;React Server Components Announcements Timeline &lt;a class=&quot;direct-link&quot; href=&quot;#react-server-components-announcements-timeline&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://react.dev/blog/2020/12/21/data-fetching-with-react-server-components&quot;&gt;“Introducing Zero-Bundle-Size React Server Components” December 2020&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=TQQPAU21ZUw&quot;&gt;“Data Fetching with React Server Components” December 2020&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/reactjs/rfcs/pull/188&quot;&gt;“RFC: React Server Components #188” December 2020 - October 2022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nextjs.org/blog/next-13#server-components&quot;&gt;“Next.js 13 (stable) #server-components” October 2022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=zMf_xeGPn6s&quot;&gt;“React from Another Dimension” by Dan Abramov at #RemixConf (May) 2023&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;react-server-components&quot;&gt;React Server Components &lt;a class=&quot;direct-link&quot; href=&quot;#react-server-components&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;React Server Components&lt;/strong&gt;, strictly speaking, are &lt;strong&gt;React components that run exclusively on the server&lt;/strong&gt;, they never run or are even hydrated on the client, in fact, &lt;strong&gt;aren&#39;t even included, bundled with alongside client-side code&lt;/strong&gt;, and thus have &lt;strong&gt;no client-side JavaScript bundle size impact&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;However, and even more importantly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Server Components allows the server and the client (browser) to collaborate in rendering your React application.&lt;br&gt;
Consider the typical React element tree that is rendered for your page, which is usually composed of different React components rendering more React components.&lt;br&gt;
RSC makes it possible for some components in this tree to be rendered by the server, and some components to be rendered by the browser.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/reactjs/rfcs/pull/188&quot;&gt;RFC: React Server Components #188&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h5 id=&quot;a-quick-note-on-%E2%80%9Creact-ssr%E2%80%9D&quot;&gt;A quick note on “React SSR” &lt;a class=&quot;direct-link&quot; href=&quot;#a-quick-note-on-%E2%80%9Creact-ssr%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;It&#39;s important to note that RSC is different than “React SSR”.&lt;br&gt;
Without diving in a &lt;strong&gt;“RSC vs React SSR”&lt;/strong&gt; comparison, I&#39;ll just mention a few points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(React) “SSR” is most commonly used to refer to the rendering on the server of a tree of React components to &lt;em&gt;inert&lt;/em&gt;, non-interactive HTML to serve a page&#39;s &lt;strong&gt;initial load&lt;/strong&gt;, the same components tree which is then potentially &lt;em&gt;hydrated&lt;/em&gt; in the client to enable interactivity&lt;/li&gt;
&lt;li&gt;RSCs, on the other hand, &lt;strong&gt;are not rendered to HTML&lt;/strong&gt;, but to a JSON-like format.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;In the &lt;strong&gt;RSC paradigm&lt;/strong&gt;, all components are Server Components by default.&lt;br&gt;
However, since an instance of a Server Component &lt;strong&gt;runs only once&lt;/strong&gt;, Server Components can only use a subset of React Component APIs, and can&#39;t use client-only APIs such as &lt;code&gt;React.useState&lt;/code&gt; / &lt;code&gt;React.useReducer&lt;/code&gt; (same thing), &lt;code&gt;React.useEffect&lt;/code&gt;, &lt;code&gt;Context.Provider&lt;/code&gt; etc.&lt;/p&gt;
&lt;p&gt;Furthermore Server Components cannot be &lt;em&gt;directly&lt;/em&gt; imported nor rendered by Client Components.&lt;br&gt;
But their serialized render output can be fetched at the server from the client &amp;amp; inserted in within a client-side components tree.&lt;/p&gt;
&lt;p&gt;Server Components also cannot render Client Components, but they can pass &lt;strong&gt;serializable props&lt;/strong&gt; to them - by “serializable” props, we mean JavaScript data types such as simple objects, arrays, strings, numbers, as well as Promises wrapping such data types, but not functions &amp;amp; classes for example.&lt;/p&gt;
&lt;h4 id=&quot;react-shared-components&quot;&gt;React Shared Components &lt;a class=&quot;direct-link&quot; href=&quot;#react-shared-components&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;React Shared Components&lt;/strong&gt; are “neutral” components: they can be both Server Components &amp;amp; Client Components - not using either of client or server specific features &amp;amp; APIs.&lt;br&gt;
As such, a given Shared Component in a React components subtree ultimately ends being either a Server Component or a Client Component, depending on the parent context in which they are rendered:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a shared component becomes a server component when it is rendered with React Server APIs or from a server component&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and conversely:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a shared component becomes a client component when it is rendered with React DOM APIs, or from a client component&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Plot twist&lt;/strong&gt;&lt;/em&gt;: components can be marked &lt;strong&gt;client-only&lt;/strong&gt; using the &lt;strong&gt;&lt;code&gt;&#39;use client&#39;&lt;/code&gt; directives&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;&#39;use-server&#39;-%26-&#39;use-client&#39;-directives&quot;&gt;&lt;code&gt;&#39;use server&#39;&lt;/code&gt; &amp;amp; &lt;code&gt;&#39;use client&#39;&lt;/code&gt; directives &lt;a class=&quot;direct-link&quot; href=&quot;#&#39;use-server&#39;-%26-&#39;use-client&#39;-directives&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Although they look similar to &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode&quot;&gt;the standard, runtime &lt;code&gt;&#39;use strict&#39;&lt;/code&gt; directive&lt;/a&gt;, &lt;code&gt;&#39;use server&#39;&lt;/code&gt; &amp;amp; &lt;code&gt;&#39;use client&#39;&lt;/code&gt; are specific to React and don&#39;t do anything by themselves or at runtime: today they&#39;re &lt;strong&gt;build-time hints for the bundler&lt;/strong&gt; (or equivalent tooling) to consider the marked modules as &lt;strong&gt;a boundary between server &amp;amp; client in the module dependency tree&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: I&#39;m not going into more details about these directives here, because the official documentation is already really good at the time of writing, and paraphrasing doesn&#39;t bring more value.&lt;br&gt;
There are a couple of caveats / subtleties that aren&#39;t necessarily covered in the official documentation, but mentioning them at this point of the blog post I think would only risk additional confusion.&lt;br&gt;
But we&#39;ll get back to these directives further in the blog post.&lt;/p&gt;
&lt;h5 id=&quot;&#39;use-client&#39;&quot;&gt;&lt;code&gt;&#39;use client&#39;&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#&#39;use-client&#39;&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;&lt;code&gt;&#39;use client&#39;&lt;/code&gt; is primarily used to mark a specific component as being client-only, including all of its components subtree.&lt;br&gt;
See &lt;a href=&quot;https://react.dev/reference/react/use-client&quot;&gt;&#39;use client&#39; official React documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h5 id=&quot;&#39;use-server&#39;&quot;&gt;&lt;code&gt;&#39;use server&#39;&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#&#39;use-server&#39;&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;See &lt;a href=&quot;https://react.dev/reference/react/use-server&quot;&gt;&#39;use server&#39; official React documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;suspense-%26-error-boundaries&quot;&gt;Suspense &amp;amp; Error Boundaries &lt;a class=&quot;direct-link&quot; href=&quot;#suspense-%26-error-boundaries&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The RSC Model leverages existing Stable React APIs such as &lt;a href=&quot;https://react.dev/reference/react/Suspense&quot;&gt;Suspense&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://react.dev/reference/react/Component#static-getderivedstatefromerror&quot;&gt;Error Boundaries&lt;/a&gt;, these two APIs in fact play an central role in the &lt;strong&gt;RSC Paradigm&lt;/strong&gt;, alongside &lt;strong&gt;the &lt;code&gt;use()&lt;/code&gt; hook, a new React Experimental API&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;use()&quot;&gt;&lt;code&gt;use()&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#use()&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I&#39;ll just mention that the &lt;code&gt;use()&lt;/code&gt; hook enables dealing with &lt;em&gt;Promises&lt;/em&gt; inside React Components.&lt;br&gt;
This is over-simplified, and we&#39;ll see in more concrete terms how to use them further in the blog post.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&quot;https://react.dev/reference/react/use&quot;&gt;&lt;code&gt;use()&lt;/code&gt; hook React Experimental API official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;demo%3A-migrating-a-react-notes-app-to-rsc-without-a-framework&quot;&gt;Demo: migrating a React Notes App to RSC without a framework &lt;a class=&quot;direct-link&quot; href=&quot;#demo%3A-migrating-a-react-notes-app-to-rsc-without-a-framework&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;a-take-home-technical-assignment-backstory&quot;&gt;A take-home technical assignment backstory &lt;a class=&quot;direct-link&quot; href=&quot;#a-take-home-technical-assignment-backstory&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;In 2020&lt;/strong&gt;, while looking for my next job, I was contacted by a well known tech company regarding a remote-friendly open position, which really resonated with my interests and I was thrilled at the opportunity.&lt;br&gt;
The hiring process required to complete a take-home technical exercise - although I&#39;m really not a fan of this hiring practice, on either side of the table - I decided that I would try.&lt;/p&gt;
&lt;h3 id=&quot;a-react-notes-app-(2020)&quot;&gt;A React Notes App (2020) &lt;a class=&quot;direct-link&quot; href=&quot;#a-react-notes-app-(2020)&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The assignment was essentially: &lt;strong&gt;build a React Notes App&lt;/strong&gt;, and then some functional UI requirements.&lt;/p&gt;
&lt;p&gt;And so I started working on building the following &lt;a href=&quot;https://react-notes-app.timtech.blog/&quot;&gt;React Notes App&lt;/a&gt; with &lt;strong&gt;Create React App&lt;/strong&gt;, &lt;a href=&quot;https://twitter.com/tpillard/status/1305889708430553088&quot;&gt;documenting my process on Twitter&lt;/a&gt; &amp;amp; publishing &lt;a href=&quot;https://github.com/ziir/react-notes-app&quot;&gt;the code on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Notes:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;while this app still holds up fairly well in my opinion, it is far from perfect, especially by today&#39;s standards.&lt;/li&gt;
&lt;li&gt;you may notice that the hosted version while functionally identical to the source code in the repository, has been optimized for bundle size, most notably by fine-tuning the Babel configuration &amp;amp; aliasing React to Preact: from 161KB (according to my notes, I haven&#39;t been bothered to run the project again locally but the details are somewhere in the ~live-tweeting) to 38.5 kB (uncompressed production build).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To wrap this up, let&#39;s just say the hiring team was pleased with my work, everything was going well after that, until the recruiter asked me if I was willing to relocate to another country (despite being clear about working remotely from France - at absolute peak COVID-19 times - and having spent many hours working on the assignment).&lt;br&gt;
Ironically, it was only after I had already accepted an offer at &lt;strong&gt;Dashlane&lt;/strong&gt; that the first company reached back to me &amp;amp; suggested starting out remotely as a contractor.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Ok, ok, but what does it all have to do with Server Components?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well I&#39;ve lately been using it this notes app as a playground for experiments &amp;amp; side projects.&lt;br&gt;
So naturally, when I started looking into RSC last week, I thought to myself:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;why not try to see to which extent I can naively migrate this simple notes app to RSC without a framework?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Actually migrating a &lt;abbr title=&quot;Create React App&quot;&gt;CRA&lt;/abbr&gt; React Notes App to RSC with no framework (2023)&lt;/h3&gt;
&lt;p&gt;No framework? Really?&lt;br&gt;
Yes! Really! It&#39;s an experiment! It&#39;s fun!&lt;br&gt;
And it&#39;s a great way to understand how things work, as well as illustrating the value of a &amp;quot;real&amp;quot; framework.&lt;br&gt;
That being said, I am a huge supporter of building your own production framework for &amp;quot;real world&amp;quot; applications if you have the opportunity, the resources and can justify it to address your use cases, it&#39;ll just need to go much further than what is described in this blog post, more on this later.&lt;/p&gt;
&lt;h3 id=&quot;disclaimer-2&quot;&gt;Disclaimer &lt;a class=&quot;direct-link&quot; href=&quot;#disclaimer-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Please note, there is absolutely nothing optimal about the following implementation, it is purposely naive, incomplete, and is intended for learning &amp;amp; demo purposes.&lt;/p&gt;
&lt;h3 id=&quot;inspiration&quot;&gt;Inspiration &lt;a class=&quot;direct-link&quot; href=&quot;#inspiration&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Our demo is inspired by &lt;a href=&quot;https://github.com/reactjs/server-components-demo&quot;&gt;React Team react server components demo from December 2020&lt;/a&gt;.&lt;br&gt;
The idea was not to re-create the demo above, or to create as good a showcase of RSC, rather to &lt;strong&gt;try&lt;/strong&gt; &amp;amp; use RSC features &amp;amp; APIs in an existing app.&lt;br&gt;
We will be borrowing some code patterns, with varying degrees of correctness &amp;amp; success.&lt;br&gt;
I also invite you to take a look at the official demo linked above &amp;amp; related materials.&lt;/p&gt;
&lt;h3 id=&quot;rsc-notes-app-demo-%2F-playground&quot;&gt;RSC Notes App Demo / Playground &lt;a class=&quot;direct-link&quot; href=&quot;#rsc-notes-app-demo-%2F-playground&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://rsc-demo.timtech.blog/&quot;&gt;Live RSC Notes App Demo / Playground&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ziir/rsc-demo&quot;&gt;Source code on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Open your browser devtools!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;objectives&quot;&gt;Objectives &lt;a class=&quot;direct-link&quot; href=&quot;#objectives&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;a somewhat functional React Notes App (listing, creating, editing &amp;amp; deleting notes with a text title &amp;amp; Markdown content)&lt;/li&gt;
&lt;li&gt;React Server Components used alongside Client Components&lt;/li&gt;
&lt;li&gt;some sort of server-side rendering&lt;/li&gt;
&lt;li&gt;some kind of data-fetching using Server Components&lt;/li&gt;
&lt;li&gt;routing that somewhat works both in the client &amp;amp; on the server&lt;/li&gt;
&lt;li&gt;refreshing server components from the client&lt;/li&gt;
&lt;li&gt;a usable RSC playground&lt;/li&gt;
&lt;li&gt;above all else: learn&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;dependencies&quot;&gt;Dependencies &lt;a class=&quot;direct-link&quot; href=&quot;#dependencies&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;node&lt;/code&gt; v18.8.1 &amp;amp; &lt;code&gt;npm&lt;/code&gt; v9.8.1&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fastify.dev/&quot;&gt;Fastify&lt;/a&gt; for the HTTP web server&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://webpack.js.org/&quot;&gt;Webpack&lt;/a&gt; bundler&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://babeljs.io/&quot;&gt;Babel&lt;/a&gt; JavaScript compiler, for transpiling JSX syntax&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/WebReflection/a-route&quot;&gt;a-route&lt;/a&gt; extremely minimal JavaScript / DOM routing library leveraging Custom Elements (also used in our original &lt;a href=&quot;#a-react-notes-app&quot;&gt;React Notes App&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;react-canary&quot;&gt;React Canary &lt;a class=&quot;direct-link&quot; href=&quot;#react-canary&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;At the time of writing, the latest React Canary release is &lt;code&gt;18.3.0-canary-8039e6d0b-20231026&lt;/code&gt;.&lt;br&gt;
We need to use the same version for the &lt;code&gt;react&lt;/code&gt; &amp;amp; &lt;code&gt;react-dom&lt;/code&gt; packages.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token property&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  ...&lt;br&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;^18.3.0-canary-8039e6d0b-20231026&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;react-dom&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;^18.3.0-canary-8039e6d0b-20231026&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  ...&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;react-server-%26-react-flight-apis&quot;&gt;React Server &amp;amp; React Flight APIs &lt;a class=&quot;direct-link&quot; href=&quot;#react-server-%26-react-flight-apis&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The traditional React dependencies are no longer sufficient when it comes to using Server Components, and for &lt;code&gt;&#39;use client&#39;&lt;/code&gt; directives to play &lt;a href=&quot;#&#39;use-server&#39;-%26-&#39;use-client&#39;-directives&quot;&gt;their role&lt;/a&gt;. For this, specialized tooling is required, and we&#39;re only interested in using what is provided by the React Team.&lt;/p&gt;
&lt;p&gt;Like the &lt;a href=&quot;#inspiration&quot;&gt;official RSC demo&lt;/a&gt; we&#39;ve mentioned earlier, we will be relying on the &lt;a href=&quot;https://github.com/facebook/react/tree/main/packages/react-server-dom-webpack&quot;&gt;react-server-dom-webpack&lt;/a&gt; package to enable RSC features.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;Experimental React Flight bindings for DOM using Webpack - Use it at your own risk&amp;quot;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; These APIs are &lt;strong&gt;completely undocumented&lt;/strong&gt; and there might be better alternatives, provided by the React Team or otherwise.&lt;/p&gt;
&lt;p&gt;In particular, we will be using the following APIs, which I&#39;ve done my best to succintly describe:&lt;/p&gt;
&lt;h5 id=&quot;react-server-dom-webpack%2Fplugin&quot;&gt;&lt;code&gt;react-server-dom-webpack/plugin&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#react-server-dom-webpack%2Fplugin&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/main/packages/react-server-dom-webpack/src/ReactFlightWebpackPlugin.js&quot;&gt;&lt;code&gt;react-server-dom-webpack/plugin&lt;/code&gt;&lt;/a&gt; is a Webpack Plugin to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generate the client chunks based on the presence of the &lt;code&gt;&#39;use client&#39;&lt;/code&gt; directive within modules.&lt;/li&gt;
&lt;li&gt;reference the client chunks &amp;amp; the other chunks they depend on in a &lt;code&gt;react-client-manifest.json&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;leverage Webpack&#39;s runtime to load the client chunks on demand: &lt;strong&gt;code splitting&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id=&quot;example-usage&quot;&gt;Example Usage &lt;a class=&quot;direct-link&quot; href=&quot;#example-usage&quot;&gt;#&lt;/a&gt;&lt;/h6&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// webpack.config.js&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ReactServerWebpackPlugin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;react-server-dom-webpack/plugin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;  plugins&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ReactServerWebpackPlugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isServer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;// react-client.manifest.json&lt;/span&gt;&lt;br&gt;  ...&lt;br&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;file:///rsc-no-framework-demo/src/app/tabs.jsx&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./src/app/tabs.jsx&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;chunks&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;client5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;client5.chunk.js&quot;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;react-server-dom-webpack%2Fnode-register&quot;&gt;&lt;code&gt;react-server-dom-webpack/node-register&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#react-server-dom-webpack%2Fnode-register&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/main/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js&quot;&gt;&lt;code&gt;react-server-dom-webpack/node-register&lt;/code&gt;&lt;/a&gt;, to create client &amp;amp; server references at runtime on the Node.js server, and creating proxies for client modules. This what effectively enables React Server Components to pass props to Client Components.&lt;/p&gt;
&lt;h6 id=&quot;example-usage-2&quot;&gt;Example Usage &lt;a class=&quot;direct-link&quot; href=&quot;#example-usage-2&quot;&gt;#&lt;/a&gt;&lt;/h6&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// server entry-point&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; reactServerRegister &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;react-server-dom-webpack/node-register&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token function&quot;&gt;reactServerRegister&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;rendertopipeablestream-from-react-server-dom-webpack%2Fserver&quot;&gt;&lt;code&gt;renderToPipeableStream&lt;/code&gt; from &lt;code&gt;react-server-dom-webpack/server&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#rendertopipeablestream-from-react-server-dom-webpack%2Fserver&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/ce2bc58a9f6f3b0bfc8c738a0d8e2a5f3a332ff5/packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js#L75&quot;&gt;&lt;code&gt;react-server-dom-webpack/server#renderToPipeableStream&lt;/code&gt;&lt;/a&gt;, renders a provided React Element with a Server Components subtree to an object matching a &lt;code&gt;PipeableStream&lt;/code&gt; interface &amp;amp; returns it, allowing the consumer to &lt;code&gt;pipe&lt;/code&gt; it to a &lt;a href=&quot;https://nodejs.org/api/stream.html#writable-streams&quot;&gt;&lt;code&gt;WritableStream&lt;/code&gt;&lt;/a&gt;. This is what effectively renders React Server Components to the &lt;strong&gt;React Flight format&lt;/strong&gt; &amp;amp; allows the output to be streamed to the client over HTTP.&lt;/p&gt;
&lt;h6 id=&quot;example-usage-3&quot;&gt;Example Usage &lt;a class=&quot;direct-link&quot; href=&quot;#example-usage-3&quot;&gt;#&lt;/a&gt;&lt;/h6&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// server.js&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MANIFEST&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;  path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../dist/react-client-manifest.json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;utf8&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MODULE_MAP&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MANIFEST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderReactTree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;writable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; component&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pipe &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderToPipeableStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;component&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token constant&quot;&gt;MODULE_MAP&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;writable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// streaming the rendering output of the App element &amp;amp; its RSC subtree&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// to the React Flight format in a Fastify route handler&lt;/span&gt;&lt;br&gt;reply&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;application/octet-stream&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token function&quot;&gt;renderReactTree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reply&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; App&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// accumulating to a string the rendering output of the App element &amp;amp; its RSC subtree&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; flightResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flightStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;stream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Writable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;chunk&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; encoding&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    flightResponse &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; chunk&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token function&quot;&gt;renderReactTree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; App&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;finished&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightStream&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;createfromreadablestream-from-react-server-dom-webpack%2Fclient&quot;&gt;&lt;code&gt;createFromReadableStream&lt;/code&gt; from &lt;code&gt;react-server-dom-webpack/client&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#createfromreadablestream-from-react-server-dom-webpack%2Fclient&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/ce2bc58a9f6f3b0bfc8c738a0d8e2a5f3a332ff5/packages/react-server-dom-webpack/src/ReactFlightDOMClientBrowser.js#L71&quot;&gt;&lt;code&gt;react-server-dom-webpack/client#createFromReadableStream&lt;/code&gt;&lt;/a&gt; is essentially a wrapper around &lt;a href=&quot;https://github.com/facebook/react/tree/main/packages/react-client&quot;&gt;&lt;strong&gt;React Flight Client API&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is an experimental package for consuming custom React streaming models.&lt;br&gt;
Its API is not as stable as that of React, React Native, or React DOM, and does not follow the common versioning scheme.&lt;br&gt;
Use it at your own risk.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Provided with a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream&quot;&gt;ReadableStream&lt;/a&gt; of &lt;strong&gt;React Flight serialized Server Components&lt;/strong&gt; data, it outputs a &lt;strong&gt;Thenable&lt;/strong&gt;, essentially reading &amp;amp; wrapping the data chunks in a &lt;strong&gt;Promise-like data structure&lt;/strong&gt;, which can be consumed by APIs dealing with &lt;strong&gt;Promises&lt;/strong&gt;, essentially the &lt;a href=&quot;#use&quot;&gt;&lt;strong&gt;&lt;code&gt;use()&lt;/code&gt; experimental hook&lt;/strong&gt;&lt;/a&gt;.&lt;br&gt;
This is the main &lt;strong&gt;RSC API&lt;/strong&gt; that allows for &lt;strong&gt;React Server Components tree output&lt;/strong&gt; computed on the server and &lt;strong&gt;serialized to the React Flight format&lt;/strong&gt; to be rendered &lt;strong&gt;on the client&lt;/strong&gt;.&lt;/p&gt;
&lt;h6 id=&quot;example-usage-4&quot;&gt;Example Usage &lt;a class=&quot;direct-link&quot; href=&quot;#example-usage-4&quot;&gt;#&lt;/a&gt;&lt;/h6&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createFromReadableStream &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react-server-dom-webpack/client&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flightTreePromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createFromReadableStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;// fake a ReadableStream with the Response constructor&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightResponseText&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;createfromfetch-from-react-server-dom-webpack%2Fclient&quot;&gt;&lt;code&gt;createFromFetch&lt;/code&gt; from &lt;code&gt;react-server-dom-webpack/client&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#createfromfetch-from-react-server-dom-webpack%2Fclient&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/ce2bc58a9f6f3b0bfc8c738a0d8e2a5f3a332ff5/packages/react-server-dom-webpack/src/ReactFlightDOMClientBrowser.js#L80&quot;&gt;&lt;code&gt;react-server-dom-webpack/client#createFromReadableStream&lt;/code&gt;&lt;/a&gt; is essentially a wrapper around &lt;a href=&quot;#createfromreadablestream-from-react-server-dom-webpackclient&quot;&gt;&lt;code&gt;createFromReadableStream&lt;/code&gt; from &lt;code&gt;react-server-dom-webpack/client&lt;/code&gt;&lt;/a&gt;, unwrapping the &lt;code&gt;Response&lt;/code&gt; promise to retrieve the underlying &lt;code&gt;ReadableStream&lt;/code&gt;.&lt;br&gt;
It serves the same purpose, but allows for the most common React Flight Client use case: rendering streamed React Server Components serialized output elements on the client, from a single &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API&quot;&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/a&gt; call.&lt;/p&gt;
&lt;h6 id=&quot;example-usage-5&quot;&gt;Example Usage &lt;a class=&quot;direct-link&quot; href=&quot;#example-usage-5&quot;&gt;#&lt;/a&gt;&lt;/h6&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;flightTreePromise&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setFlightTreePromise&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;  initialFlightTreePromise&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; refreshFlightTreePromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createFromFetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/react-flight?props=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;encodeURIComponent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token function&quot;&gt;setFlightTreePromise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;refreshFlightTreePromise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightTreePromise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;our-first-react-server-component&quot;&gt;Our first React Server Component &lt;a class=&quot;direct-link&quot; href=&quot;#our-first-react-server-component&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In this hypothetical example, &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; and all its subtree are Shared Components.&lt;br&gt;
They do not use any client-specific APIs, they can be both Server Components or Client Components, they can be both rendered on the server or on the client.&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Layout&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Header&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Layout&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because we will be rendering the &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; component and its subtree with React Server APIs, all these components are automatically Server Components.&lt;br&gt;
The rendering of the &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; component, even though it is streamed, can be considered synchronous: a single &lt;strong&gt;React Flight chunk&lt;/strong&gt; is emitted.&lt;/p&gt;
&lt;h3 id=&quot;server-side-rendering-of-server-components&quot;&gt;Server-Side Rendering of Server Components &lt;a class=&quot;direct-link&quot; href=&quot;#server-side-rendering-of-server-components&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;#react-server--react-flight-apis&quot;&gt;React Server &amp;amp; React Flight APIs&lt;/a&gt; being completely undocumented as mentioned earlier, properly rendering output of React Server Components to HTML, and streaming it efficiently to the browser, without a framework, is quite challenging.&lt;br&gt;
Indeed, while it is relatively straightforward to obtain the rendering output of a server components tree in the React Flight Format (also known as the &lt;strong&gt;RSC payload&lt;/strong&gt;), as a &lt;code&gt;PipeableStream&lt;/code&gt; or a string using these APIs - &lt;a href=&quot;#rendertopipeablestream-from-react-server-dom-webpackserver&quot;&gt;renderToPipeableStream&lt;/a&gt; in particular - at the time of writing, I don&#39;t know how to efficiently translate it to HTML - and I was too lazy to deep dive in Next.js&#39; implementation.&lt;br&gt;
But for the purposes of learning &amp;amp; demonstration, we really want to do &lt;em&gt;something, anything&lt;/em&gt; that ressembles Server Components SSR.&lt;/p&gt;
&lt;h4 id=&quot;an-unorthodox-ssr-implementation&quot;&gt;An Unorthodox SSR Implementation &lt;a class=&quot;direct-link&quot; href=&quot;#an-unorthodox-ssr-implementation&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;h5 id=&quot;traditional-ssr-store-serialization&quot;&gt;Traditional SSR Store Serialization &lt;a class=&quot;direct-link&quot; href=&quot;#traditional-ssr-store-serialization&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Traditionally, one way of doing React SSR is to fetch necessary data prior to or while rendering the application, using React DOM Server APIs, such as &lt;code&gt;ReactDOM.renderToString()&lt;/code&gt;.&lt;br&gt;
As the data is fetched, it populates a store such as a Redux store.&lt;/p&gt;
&lt;p&gt;Once the rendering of the application is completed, the Redux store is serialized to JSON, so it can be used as the client-side application&#39;s store initial state.&lt;br&gt;
In order to be picked up when the client application loads, the serialized store output is generally included at the end of the HTML document, as a JSON string inside a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag, or as a &lt;code&gt;string&lt;/code&gt; or assigned directly to a variable with &lt;code&gt;const state = JSON.parse(&#39;{serialized_store}&#39;)&lt;/code&gt;.&lt;br&gt;
This is necessary to correctly hydrate the sever-side rendered React tree, allowing client-side React to re-run the components tree with the same data used for the server-side rendering.&lt;/p&gt;
&lt;h5 id=&quot;server-components-react-flight-output-serialization&quot;&gt;Server Components React Flight Output Serialization &lt;a class=&quot;direct-link&quot; href=&quot;#server-components-react-flight-output-serialization&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;As Server Components are rendered to the &lt;strong&gt;serialized React Flight format&lt;/strong&gt;, we can apply the same technique to the &lt;strong&gt;RSC payload&lt;/strong&gt;.&lt;br&gt;
Of course, this is incredibly suboptimal, and eliminates most of the benefits of Server-side rendering.&lt;/p&gt;
&lt;p&gt;We actually shouldn&#39;t even call it Server-side rendering, because the Server components tree is not even rendered as HTML in the served initial HTML document, and JavaScript is necessary to render the RSC tree into the DOM.&lt;/p&gt;
&lt;p&gt;But regardless, this still has some benefits: we don&#39;t have to make one extra Fetch HTTP request when the client-side app loads to retrieve the RSC tree: the data is already there on first load, serialized in the DOM or in a JavaScript variable, at the cost of a higher &lt;abbr title=&quot;Time To First Byte&quot;&gt;TTFB&lt;/abbr&gt;.&lt;br&gt;
Good enough for a first try, and a good first exposure to the relevant React Server / Client APIs, but what would that look like?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; actually, this technique may be a good fit for a specific variant of SSG, where the Server Components are rendered during the build process, and only static files are shipped to production.&lt;/p&gt;
&lt;h5 id=&quot;inlining-server-components-output-into-the-html-shell&quot;&gt;Inlining Server Components Output into the HTML Shell &lt;a class=&quot;direct-link&quot; href=&quot;#inlining-server-components-output-into-the-html-shell&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;First, we need to adapt our &lt;code&gt;index.html&lt;/code&gt; HTML shell template, and define a slot to inject our React Flight data.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;react-flight&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;react/flight&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br&gt;    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;FLIGHT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, in our web server (here, written with Fastify), create a route handler that will render our React Server Components tree into a &lt;em&gt;PipeableStream&lt;/em&gt;, which we &lt;code&gt;pipe&lt;/code&gt; to our &lt;code&gt;flightStream&lt;/code&gt; &lt;em&gt;WritableStream&lt;/em&gt;, letting us accumulate the React Flight chunks into a string.&lt;br&gt;
We then &lt;code&gt;await finished(flightStream)&lt;/code&gt; to wait for all the chunks to be written, and finally inject the complete React Flight Response in our template.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; readFileSync &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;node:fs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;node:stream&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; finished &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;node:stream/promises&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; React &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; renderToPipeableStream &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;react-server-dom-webpack/server&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; App &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;../src/app/app&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MANIFEST&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;  path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../dist/react-client-manifest.json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;utf8&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MODULE_MAP&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MANIFEST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HTML_SHELL&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;  path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../dist/index.html&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;utf8&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderReactTree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;writable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; component&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pipe &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderToPipeableStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;component&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token constant&quot;&gt;MODULE_MAP&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;writable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fastify &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Fastify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;fastify&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;routeHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; flightResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flightStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;stream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Writable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token function-variable function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;chunk&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; encoding&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;      flightResponse &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; chunk&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token function&quot;&gt;renderReactTree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; App&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;finished&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightStream&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  reply&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;text/html&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HTML_SHELL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;!--FLIGHT--&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightResponse&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we&#39;re able to render React Server Components on the server, and inline the output data inside our HTML template.&lt;br&gt;
Nice, but how do we then pick that up to be rendered on the client?&lt;/p&gt;
&lt;h5 id=&quot;rendering-server-components-output-on-the-client&quot;&gt;Rendering Server Components Output on the Client &lt;a class=&quot;direct-link&quot; href=&quot;#rendering-server-components-output-on-the-client&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;We first need to retrieve the inlined React Flight data from the DOM &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag, transform it into a &lt;em&gt;ReadableStream&lt;/em&gt; (here using the &lt;code&gt;Response().body&lt;/code&gt; trick for convenience), before we feed it to React Flight Client API &lt;code&gt;createFromReadableStream&lt;/code&gt; &amp;amp; obtain a Promise-like object, which we can finally pass to the &lt;code&gt;use()&lt;/code&gt; hook from our &lt;code&gt;&amp;lt;Root /&amp;gt;&lt;/code&gt; application root React Component.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createElement&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; use &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createRoot &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react-dom/client&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createFromReadableStream &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react-server-dom-webpack/client&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Root&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; flightTreePromise &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightTreePromise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flightEl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;react-flight&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flightResponseText &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightEl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flightTreePromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createFromReadableStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flightResponseText&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; root &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createRoot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;root&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Root flightTreePromise&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;flightTreePromise&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;data-fetching-in-server-components&quot;&gt;Data-Fetching in Server Components &lt;a class=&quot;direct-link&quot; href=&quot;#data-fetching-in-server-components&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;adding-data-fetching-with-async-%2F-await&quot;&gt;Adding Data-Fetching with &lt;code&gt;async&lt;/code&gt; / &lt;code&gt;await&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#adding-data-fetching-with-async-%2F-await&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Layout&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Header&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Layout&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The rendering of the &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; component becomes truly asynchronous, it is &lt;em&gt;streamed&lt;/em&gt; in multiple chunks, starting with a first chunk, immediately before the &lt;code&gt;await&lt;/code&gt;, then followed by the remaining second chunk after the &lt;code&gt;Promise&lt;/code&gt; resolves, including the rendering output of the &lt;code&gt;&amp;lt;Layout&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Header /&amp;gt;&lt;/code&gt; &amp;amp; &lt;code&gt;&amp;lt;List&amp;gt;&lt;/code&gt; components.&lt;/p&gt;
&lt;h4 id=&quot;data-fetching-in-child-components%3A-waterfall%3F&quot;&gt;Data-Fetching in child components: waterfall? &lt;a class=&quot;direct-link&quot; href=&quot;#data-fetching-in-child-components%3A-waterfall%3F&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Let&#39;s now make the &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component &lt;code&gt;async&lt;/code&gt; with a similar data-fetching constraint.&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; items &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The rendering of the &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component only starts after the &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt;&#39;s awaited &lt;em&gt;Promise&lt;/em&gt; resolves, and the awaited &lt;em&gt;Promise&lt;/em&gt; of &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; in turn, blocks the rendering of further child components. The second chunk now only includes the output of the &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; component, the output of the &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component is only emitted in a third chunk, after it&#39;s awaited &lt;code&gt;Promise&lt;/code&gt; has resolved.&lt;/p&gt;
&lt;p&gt;In other words,the Server Components tree is rendered &amp;amp; streamed asynchronously, naive use of &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; for &lt;strong&gt;data-fetching in server components&lt;/strong&gt; induces a &lt;strong&gt;waterfall&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Are there other options available to us?&lt;/p&gt;
&lt;h4 id=&quot;moving-the-async%2Fawait-down&quot;&gt;Moving the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; down &lt;a class=&quot;direct-link&quot; href=&quot;#moving-the-async%2Fawait-down&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Let&#39;s simplify our &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; for clarity, and adapt it to trigger data-fetching at render-time as previously, but we remove the &lt;code&gt;async&lt;/code&gt; / &lt;code&gt;await&lt;/code&gt; from it, and move the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; down to the &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; itemsPromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemsPromise&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;itemsPromise&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; itemsPromise &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; itemsPromise&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A fourth chunk makes its appearance, containing the output of the &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component, after the &lt;code&gt;await&lt;/code&gt; of the &lt;code&gt;itemsPromise&lt;/code&gt; Promise has resolved.&lt;br&gt;
Although this is progress, in that instead of passing a resolved Promise value prop to children, we&#39;re passing a Promise props directly, and the component actually making use of the Promise is the one &lt;code&gt;await&lt;/code&gt;ing it, without blocking the rendering of (or data-fetching inside) other children of the &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; component: still a waterfall, still idiomatic JavaScript &amp;amp; Promise handling, but slightly better&lt;/p&gt;
&lt;p&gt;We mentioned earlier that React Server Components integrate with &lt;strong&gt;Suspense&lt;/strong&gt;, but how do we leverage it?&lt;/p&gt;
&lt;h4 id=&quot;suspense-enabled-streaming&quot;&gt;Suspense-enabled streaming &lt;a class=&quot;direct-link&quot; href=&quot;#suspense-enabled-streaming&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;h5 id=&quot;with-async%2Fawait&quot;&gt;With async/await &lt;a class=&quot;direct-link&quot; href=&quot;#with-async%2Fawait&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Using &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; &lt;strong&gt;in Server Components&lt;/strong&gt; is compatible with &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt;, so all we need to do is to wrap it around our &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component, and give it a &lt;code&gt;fallback&lt;/code&gt; &lt;em&gt;React Node&lt;/em&gt;, to be used while the &lt;em&gt;Promise&lt;/em&gt; is &lt;em&gt;pending&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;rendering &amp;lt;App /&gt; component&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; itemsPromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Suspense-enabled streaming&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Suspense&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fallback&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Loading ...&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemsPromise&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;itemsPromise&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Suspense&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; itemsPromise &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;before the await&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; itemsPromise&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;after the await&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;List&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see in our server logs the following sequence:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rendering &amp;lt;App /&amp;gt; component
before the await
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then as you&#39;d expect, one second later:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;after the await
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which translates to the following &lt;em&gt;React Flight chunks (RSC Payload)&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1:&amp;quot;$Sreact.suspense&amp;quot;
0:[&amp;quot;$&amp;quot;,&amp;quot;$1&amp;quot;,null,{&amp;quot;fallback&amp;quot;:&amp;quot;Loading ...&amp;quot;,&amp;quot;children&amp;quot;:&amp;quot;$L2&amp;quot;}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then one second later:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2:[&amp;quot;$&amp;quot;,&amp;quot;ul&amp;quot;,null,{&amp;quot;className&amp;quot;:&amp;quot;List&amp;quot;,&amp;quot;children&amp;quot;:[[&amp;quot;$&amp;quot;,&amp;quot;li&amp;quot;,null,{&amp;quot;children&amp;quot;:&amp;quot;Suspense-enabled streaming&amp;quot;}]]}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The usage of &lt;code&gt;async / await&lt;/code&gt; in a &lt;strong&gt;Server Component wrapped in Suspense&lt;/strong&gt; causes said component&#39;s render to be &lt;strong&gt;postponed&lt;/strong&gt;.&lt;br&gt;
This is the idiomatic, recommended pattern for &lt;strong&gt;data-fetching in Server Components with Suspense&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In the browser - with either a specific SSR implementation with RSC streaming support, or a client app able to render streamed React Flight chunks - this would result in the following sequence displayed on the screen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;render the &lt;code&gt;Loading...&lt;/code&gt; suspense fallback&lt;/li&gt;
&lt;li&gt;wait 1second for the next chunk to come in&lt;/li&gt;
&lt;li&gt;replace the &lt;code&gt;Loading...&lt;/code&gt; suspense fallback with the following HTML / DOM:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Suspense-enabled streaming&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But what about &lt;a href=&quot;#use&quot;&gt;&lt;code&gt;use()&lt;/code&gt; experimental hook&lt;/a&gt;?&lt;br&gt;
Didn&#39;t we say that &lt;code&gt;use()&lt;/code&gt; allowed us to handle Promises in components, in conjunction with &lt;em&gt;Suspense&lt;/em&gt;?&lt;/p&gt;
&lt;h5 id=&quot;use()-vs-async%2Fawait&quot;&gt;use() vs async/await &lt;a class=&quot;direct-link&quot; href=&quot;#use()-vs-async%2Fawait&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;The &lt;a href=&quot;#use&quot;&gt;&lt;code&gt;use()&lt;/code&gt; experimental hook&lt;/a&gt; indeed lets us consume Promises inside React Components.&lt;br&gt;
If we take the code of our &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; &lt;strong&gt;server component&lt;/strong&gt; from the previous example, remove the &lt;strong&gt;async / await&lt;/strong&gt; and replace it with &lt;code&gt;use(itemsPromise)&lt;/code&gt; instead, our server components behave &lt;strong&gt;almost&lt;/strong&gt; the same:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; use &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;react&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; itemsPromise &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;before the use()&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;itemsPromise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;after the use()&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The practical &lt;strong&gt;difference between use() and async/await&lt;/strong&gt; in server components is that in the &lt;code&gt;use()&lt;/code&gt; case, the &lt;strong&gt;use&lt;/strong&gt; hook tracks the state of the provided &lt;em&gt;Promise&lt;/em&gt;, by checking its &lt;code&gt;Thenable.status&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if the &lt;code&gt;Thenable.status&lt;/code&gt; is &lt;code&gt;pending&lt;/code&gt; or &lt;code&gt;rejected&lt;/code&gt;, it &lt;strong&gt;suspends&lt;/strong&gt; (interrupts) the rendering of the component&lt;/li&gt;
&lt;li&gt;if the &lt;code&gt;Thenable.status&lt;/code&gt; is &lt;code&gt;fulfilled&lt;/code&gt;, it returns the resolved value, and &lt;em&gt;resumes&lt;/em&gt; rendering the component&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The rendering of a component &lt;strong&gt;suspended&lt;/strong&gt; with &lt;em&gt;use()&lt;/em&gt; - contrarily to a &lt;strong&gt;postponed&lt;/strong&gt; server component with &lt;em&gt;async/await&lt;/em&gt; - will be &lt;em&gt;resumed&lt;/em&gt; once the &lt;em&gt;Thenable&lt;/em&gt; (Promise) ultimately resolves.&lt;br&gt;
Effectively, the render of the component is &lt;strong&gt;replayed&lt;/strong&gt;.&lt;br&gt;
The details of the &lt;em&gt;use() hook&lt;/em&gt; are complex, but we can observe the general behavior in our server logs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rendering &amp;lt;App /&amp;gt; component
before the use()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then one second later:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;before the use()
after the use()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice how the &lt;code&gt;before the use()&lt;/code&gt; message is logged twice.&lt;br&gt;
The &lt;code&gt;use()&lt;/code&gt; hook has caused our &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component to &lt;strong&gt;suspend&lt;/strong&gt;, and once &lt;code&gt;itemsPromise&lt;/code&gt; has resolved, its rendering is &lt;em&gt;resumed&lt;/em&gt; by being &lt;strong&gt;replayed&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This translates to both an identical &lt;strong&gt;RSC Payload&lt;/strong&gt;, and an identical output displayed in the browser, as in the previous example with &lt;code&gt;async/await&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&quot;passing-the-server&#39;s-pending-promise-to-the-client&quot;&gt;Passing the Server&#39;s pending Promise to the Client &lt;a class=&quot;direct-link&quot; href=&quot;#passing-the-server&#39;s-pending-promise-to-the-client&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Honestly, this is all already pretty good.&lt;br&gt;
But we can go even further than that: what if we could &lt;strong&gt;start fetching data on the server&lt;/strong&gt; and directly &lt;em&gt;consume the Promise on the client&lt;/em&gt;?&lt;br&gt;
Let&#39;s consider &lt;em&gt;the perfect use() case&lt;/em&gt;: that our &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component, is in fact a &lt;em&gt;Client Component&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;First, we need to add the &lt;a href=&quot;#&#39;use-client&#39;&quot;&gt;&lt;code&gt;&#39;use client&#39;&lt;/code&gt; directive&lt;/a&gt; to our &lt;code&gt;list.jsx&lt;/code&gt; module.&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use client&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// List component ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As previously, we still want to consume the &lt;code&gt;itemsPromise&lt;/code&gt; in the &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component.&lt;br&gt;
But our &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; component is &lt;strong&gt;now a Client Component&lt;/strong&gt;, and as such, cannot be &lt;code&gt;async&lt;/code&gt;, thus cannot use &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The solution, you&#39;ve guessed it, is with the &lt;em&gt;use()&lt;/em&gt; hook.&lt;/p&gt;
&lt;h5 id=&quot;use()-the-force%2C-luke&quot;&gt;&lt;code&gt;use()&lt;/code&gt; the force, Luke &lt;a class=&quot;direct-link&quot; href=&quot;#use()-the-force%2C-luke&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use client&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; itemsPromise &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;// `itemsPromise` is passed from a Server Component to a Client Component!&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;itemsPromise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This results in the following &lt;em&gt;RSC Flight chunks&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1:&amp;quot;$Sreact.suspense&amp;quot;
2:I[&amp;quot;./src/app/list.jsx&amp;quot;,[&amp;quot;client3&amp;quot;,&amp;quot;client3.chunk.js&amp;quot;],&amp;quot;List&amp;quot;]
0:[&amp;quot;$&amp;quot;,&amp;quot;$1&amp;quot;,null,{&amp;quot;fallback&amp;quot;:&amp;quot;Loading ...&amp;quot;,&amp;quot;children&amp;quot;:[&amp;quot;$&amp;quot;,&amp;quot;$L2&amp;quot;,null,{&amp;quot;itemsPromise&amp;quot;:&amp;quot;$@3&amp;quot;}]}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then one-second later, the contents of our &lt;code&gt;itemsPromise&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;3:[&amp;quot;Suspense-enabled streaming&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is where things get really interesting - to be continued...&lt;/p&gt;
&lt;h4 id=&quot;waterfall-waterfall-waterfall&quot;&gt;Waterfall waterfall waterfall &lt;a class=&quot;direct-link&quot; href=&quot;#waterfall-waterfall-waterfall&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;We succeeded in performing React Server Components Suspense-enabled data-fetching &amp;amp; streamed rendering!&lt;br&gt;
This is great! It&#39;s better than our previous solutions of &lt;code&gt;await&lt;/code&gt;ing Promises in any component, because our solution now correctly leverages &lt;code&gt;&amp;lt;Suspense /&amp;gt;&lt;/code&gt;!&lt;br&gt;
But what about the &lt;em&gt;waterfall&lt;/em&gt;? We only have a single (&lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt;) component that is doing data-fetching, and only a single component (&lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt;) consuming an &lt;strong&gt;async data source&lt;/strong&gt; here...&lt;/p&gt;
&lt;p&gt;If we add another async component with &lt;code&gt;await&lt;/code&gt; (or &lt;code&gt;use()&lt;/code&gt;) anywhere in the &lt;code&gt;&amp;lt;List /&amp;gt;&lt;/code&gt; subtree, we will still be introducing an &lt;strong&gt;async waterfall&lt;/strong&gt;.&lt;br&gt;
&lt;strong&gt;Fetching data in components is inherently subject to waterfall&lt;/strong&gt;, even when leveraging best practices with &lt;em&gt;React Server Components, Suspense, async rendering&lt;/em&gt;, simply because the data fetching within a component, cannot start until this component has started to render, which is potentially blocked by the data-fetching of the parent component.&lt;/p&gt;
&lt;p&gt;And &lt;em&gt;that&#39;s fine actually™&lt;/em&gt;: even though waterfall results in slightly suboptimal UX, it doesn&#39;t mean it&#39;s bad UX either!&lt;br&gt;
Most of the time, waterfalls - even without all the combined benefits of RSC &amp;amp; Suspense - can yield a perfectly satisfactory experience.&lt;br&gt;
And when it doesn&#39;t, there are multiple ways to mitigate the waterfall itself or its impact: &lt;strong&gt;composition&lt;/strong&gt;, moving data-fetching up or down the tree, backend for frontend, optimizing, adapting or re-designing the API, etc...&lt;/p&gt;
&lt;p&gt;Alternatively, if one really wants to avoid the waterfall problem inherent to fetching data from components, then one must move the data fetching &lt;strong&gt;outside&lt;/strong&gt; of the component.&lt;br&gt;
This problem has been known for a long time now and frameworks, libraries &amp;amp; patterns exist to solve it, such as Remix / React Router Loaders or Relay / GraphQL, in which case, the data requirements are defined, not in the component, but generally in the module, alongside the component.&lt;/p&gt;
&lt;p&gt;Further alternatively, components could be responsible for defining their data requirements &amp;quot;what to fetch&amp;quot;, and delegating the actual data-fetching to another system.&lt;/p&gt;
&lt;p&gt;Finally, there might be compilers which will attempt to &lt;em&gt;optimize data-fetching in RSC&lt;/em&gt;, and eliminate or mitigate &lt;strong&gt;some&lt;/strong&gt; waterfalls automatically.&lt;/p&gt;
&lt;h3 id=&quot;routing-with-server-components%3F&quot;&gt;Routing with Server Components? &lt;a class=&quot;direct-link&quot; href=&quot;#routing-with-server-components%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Our original React Notes App uses a custom Router, leveraging the React Context API &amp;amp; the &lt;a href=&quot;https://github.com/WebReflection/a-route&quot;&gt;a-route&lt;/a&gt; library.&lt;br&gt;
As such, it is client-side only &amp;amp; does not work with React Server Components.&lt;br&gt;
In fact, the majority of the React Routing tooling out there, won&#39;t work with React Server Components.&lt;/p&gt;
&lt;p&gt;I had to make a few tweaks to the original router implementation in our RSC Notes App, here is the (suboptimal) outcome:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the (not great) initial implementation of the router was completely broken when I migrated to RSC, partly due to now unnecessary use of &lt;code&gt;useEffect&lt;/code&gt; &amp;amp; render-functions.&lt;/li&gt;
&lt;li&gt;routes and their matching component are defined in a &lt;code&gt;routes.js&lt;/code&gt; module, which is imported both on the server &amp;amp; on the client&lt;/li&gt;
&lt;li&gt;routes are matched both on the server for the initial load, and on the client for client-side navigation&lt;/li&gt;
&lt;li&gt;routes can be matched similarly by chance, because &lt;code&gt;a-route&lt;/code&gt;&#39;s route matching is similar to Express&#39; with &lt;a href=&quot;https://github.com/pillarjs/path-to-regexp&quot;&gt;path-to-regexp&lt;/a&gt;, and Fastify uses a similar route format&lt;/li&gt;
&lt;li&gt;after matching the route on the server, we deduce a &lt;code&gt;location&lt;/code&gt; object which is similar to the few properties of &lt;code&gt;window.location&lt;/code&gt; we use on the client&lt;/li&gt;
&lt;li&gt;the routing props are passed when rendering the &lt;code&gt;App&lt;/code&gt; server component, so server components can use that&lt;/li&gt;
&lt;li&gt;the client-side router is autonomous, doesn&#39;t rely on values computed on the client&lt;/li&gt;
&lt;li&gt;all routes are Client Components, only the root component including the layout shared by all routes, as well as some of its children, are server components in our implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But all in all, our solution kinda works and &lt;strong&gt;the app is functional&lt;/strong&gt;, objective completed!&lt;/p&gt;
&lt;p&gt;A couple more things I would like to mention here in regard to routing with Server Components is that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Route components should probably either be all client components or server components, supporting both risks being formidably complex &amp;amp; confusing for the developer.&lt;/li&gt;
&lt;li&gt;The route matching logic should live outside of React, so it can be used on the server as well.&lt;/li&gt;
&lt;li&gt;Moving route paths &amp;amp; components definition outside of React, ie, in a boring module which can be imported, makes things easier.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I invite you to take a look at our RSC React Notes App routing implementation &amp;amp; experiment for yourself.&lt;br&gt;
Maybe try to plug-in some of the most popular React routing libraries out there, see what happens.&lt;br&gt;
Maybe I&#39;ll try some things myself and update this section at a later time.&lt;/p&gt;
&lt;h3 id=&quot;form-handling-with-server-components&quot;&gt;Form handling with Server Components &lt;a class=&quot;direct-link&quot; href=&quot;#form-handling-with-server-components&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I didn&#39;t have the opportunity to experiment a lot with form handling in server components for two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Server Actions for example are not supported by our setup&lt;/li&gt;
&lt;li&gt;our forms (note creation, edition, deletion) are all client-side:
&lt;ul&gt;
&lt;li&gt;due to limitations of our router implementation&lt;/li&gt;
&lt;li&gt;to prevent abuse (since the demo is hosted &amp;amp; available to the public)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But I took the opportunity to play with &lt;strong&gt;React Client Actions&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;react-client-actions&quot;&gt;React Client Actions &lt;a class=&quot;direct-link&quot; href=&quot;#react-client-actions&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;React Client Actions&lt;/strong&gt; (like React Server Actions) are &lt;strong&gt;async functions&lt;/strong&gt; that can be passed to the &lt;code&gt;&amp;lt;form action={...}&amp;gt;&lt;/code&gt; &amp;amp; &lt;code&gt;&amp;lt;button formAction={...}&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;input type=&amp;quot;submit&amp;quot; formAction={...} /&amp;gt;&lt;/code&gt; &lt;strong&gt;React host / native elements props&lt;/strong&gt;.&lt;br&gt;
In the case of Client Actions only, they allow developers to write form handling logic, slightly more efficiently, and handle form submission render updates to be handled asynchronously by React.&lt;/p&gt;
&lt;p&gt;Until now, these props were expected to follow the&lt;br&gt;
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action&quot;&gt;&lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; Form HTML Element&#39;s &lt;code&gt;action&lt;/code&gt;&lt;/a&gt; &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#formaction&quot;&gt;&lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; Form HTML Element&#39;s &lt;code&gt;formaction&lt;/code&gt;&lt;/a&gt; attributes &lt;strong&gt;standard behavior&lt;/strong&gt;, but not anymore: with Server / Client actions: they accept async functions.&lt;/p&gt;
&lt;p&gt;Server / Client Actions encourage &lt;a href=&quot;https://htmx.org/essays/locality-of-behaviour/&quot;&gt;Locality of Behaviour&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, in our original React Notes App, we use the same &lt;code&gt;&amp;lt;Form /&amp;gt;&lt;/code&gt; component in the &lt;code&gt;Create&lt;/code&gt; &amp;amp; &lt;code&gt;Edit&lt;/code&gt; route components.&lt;br&gt;
Therefore the note creation &amp;amp; edition logic is actually split between two components.&lt;br&gt;
So our &lt;code&gt;Form.jsx&lt;/code&gt; component looks a little bit like this:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useState &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  formId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  handleAction&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;&lt;br&gt;  children&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; renderAdjacent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;&lt;br&gt;  item &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; item &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;submitting&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setSubmitting&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;formId&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Form&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token attr-name&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleFormAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;formData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;          &lt;span class=&quot;token function&quot;&gt;setSubmitting&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;          &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromEntries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;          &lt;span class=&quot;token function&quot;&gt;setSubmitting&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;        ...&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Form-actions&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;        &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; renderAdjacent &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderAdjacent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; submitting &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And our &lt;code&gt;Create.jsx&lt;/code&gt; component, like this:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use client&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useRouter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./router&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useItemMutation &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./items&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Form &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./form&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Button &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./button&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; generateId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../utils/id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; router &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useRouter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; addItem &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useItemMutation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Create&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt;&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token attr-name&quot;&gt;formId&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;create-form&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token attr-name&quot;&gt;handleAction&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleCreateAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;          &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; item &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;            &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;values&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;            id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;generateId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;          &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;          &lt;span class=&quot;token function&quot;&gt;addItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;          router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;navigate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/view/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;        &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; submitting &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;create-form&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;disabled&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;submitting&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;            Create&lt;br&gt;          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you may notice, our implementation relies on a &lt;code&gt;submitting&lt;/code&gt; React state variable.&lt;br&gt;
I wanted to use the new &lt;a href=&quot;https://react.dev/reference/react-dom/hooks/useFormStatus&quot;&gt;useFormStatus&lt;/a&gt; experimental hook in the &lt;code&gt;Create&lt;/code&gt; component to enable the &lt;code&gt;disabled&lt;/code&gt; prop on our &lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt; component when the form is &lt;code&gt;submitting&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately, this is not possible because &lt;code&gt;useFormStatus&lt;/code&gt; only works for components rendered within a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element, and our submit button actually lives &lt;strong&gt;outside of the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element&lt;/strong&gt;.&lt;br&gt;
This can be easily fixed by creating a &lt;code&gt;&amp;lt;SubmitButton /&amp;gt;&lt;/code&gt; component and rendering it as part of the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; subtree.&lt;/p&gt;
&lt;p&gt;However, rendering form submit buttons outside of a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element, leveraging the &lt;code&gt;form&lt;/code&gt; property with a form &lt;code&gt;id&lt;/code&gt; is very common nowadays.&lt;br&gt;
I wish we could have used the &lt;code&gt;useFormStatus&lt;/code&gt; hook outside of a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element, possibly supplying it a &lt;code&gt;formId&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;should-you-be-writing-your-own-rsc-framework%3F&quot;&gt;Should you be writing your own RSC framework? &lt;a class=&quot;direct-link&quot; href=&quot;#should-you-be-writing-your-own-rsc-framework%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There is no doubt, the RSC model is very powerful.&lt;/p&gt;
&lt;p&gt;As we&#39;ve seen together, implementing it &lt;em&gt;from scratch&lt;/em&gt; is not going to be an easy feat, due to the inherent complexity of React Server Components of course, and in my opinion, due to the lack of shared building blocks provided by the React Team, and the fact that the ones provided are largely under-documented today.&lt;br&gt;
Which of course leads to frameworks (Next.js) owning a very large part of the model - and necessarily leading to slightly different implementations, probably incompatible with one another.&lt;/p&gt;
&lt;p&gt;Therefore I would not recommend product or platform teams to implement their own RSC framework in the current state of things.&lt;br&gt;
However, I do recommend individuals, Open Source contributors to experiment with this technology and challenge the status-quo.&lt;br&gt;
I know some exceptionally smart &amp;amp; capable folks (much more than me) in the community are actively reverse-engineering Next.js &amp;amp; driving innovation, I just wish there &lt;strong&gt;more&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;should-you-be-migrating-your-full-stack-react-framework-to-rsc%3F&quot;&gt;Should you be migrating your Full-Stack React Framework to RSC? &lt;a class=&quot;direct-link&quot; href=&quot;#should-you-be-migrating-your-full-stack-react-framework-to-rsc%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a trick question.&lt;/p&gt;
&lt;p&gt;On one hand, I absolutely want to recommend teams with an existing in-house Full-Stack React Framework to &lt;strong&gt;progressively migrate to RSC&lt;/strong&gt;.&lt;br&gt;
On the other hand, this is going to be a tremendous amount of research, reverse-engineering, migration &amp;amp; documentation work that will span over months if not years.&lt;/p&gt;
&lt;p&gt;But at the same time, chances are, a move to RSC is going to allow you to modernize your architecture, leverage &lt;s&gt;experimental&lt;/s&gt; modern React features, improve the architecture of your applications, write more efficient code more efficiently while also being a formidable catalyst for removing legacy debt.&lt;/p&gt;
&lt;p&gt;Conceptually, RSC features allow to simplify or completely remove a lot of things that your framework was doing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;code-splitting&lt;/strong&gt; becomes infinitely easier if not automatic with &lt;code&gt;&#39;use client&#39;&lt;/code&gt; whereas it was probably manual previously (if it was even in place)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;server-side data-fetching in components&lt;/strong&gt; is baked-in whereas it was previously entirely custom &amp;amp; full of caveats (ie: confined to route components, relying on a feature of a specific router library)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSR streaming&lt;/strong&gt; although currently incomplete (to my knowledge) as provided by the React Team today, is incredibly more efficient with React Flight than anything we&#39;ve seen or done before&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;progressive enhancement&lt;/strong&gt; with Server Actions, despite their downsides, is likely to be a better solution than whatever we used to do to handle React form submissions without JavaScript&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;expensive components rendering&lt;/strong&gt; can in some cases be moved to the server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;bundle size reduction&lt;/strong&gt; with Server Components &amp;amp; Server Actions, huge JavaScript libraries can be moved to the server while only their final output is sent to the client&lt;/li&gt;
&lt;li&gt;and more!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In any case, I would honestly &lt;strong&gt;wait a bit longer&lt;/strong&gt;.&lt;br&gt;
There are plenty of debates about RSC &amp;amp; other modern / experimental React features being stable or production-ready (and more) going on these days.&lt;br&gt;
It&#39;s pretty obvious from the content of this blog post, despite my potential mistakes and it not being exhaustive, that this debate is legitimate.&lt;br&gt;
I also think there needs to be more &lt;em&gt;divesity&lt;/em&gt; &amp;amp; &lt;strong&gt;a wider adoption&lt;/strong&gt; in the ecosystem.&lt;/p&gt;
&lt;h2 id=&quot;going-further-with-rsc&quot;&gt;Going further with RSC &lt;a class=&quot;direct-link&quot; href=&quot;#going-further-with-rsc&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;server-only-%26-client-only-packages&quot;&gt;server-only &amp;amp; client-only packages &lt;a class=&quot;direct-link&quot; href=&quot;#server-only-%26-client-only-packages&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.npmjs.com/package/server-only?activeTab=code&quot;&gt;&lt;code&gt;server-only&lt;/code&gt;&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://www.npmjs.com/package/client-only?activeTab=code&quot;&gt;&lt;code&gt;client-only&lt;/code&gt;&lt;/a&gt; packages (or equivalent) are strongly recommended when working with RSC / Server Actions, for security reasons first, and potentially bundle size or load/runtime performance second.&lt;br&gt;
These packages help preventing that code, supposed to run exclusively on the server, to be inadvertently imported from client code, or vice versa.&lt;/p&gt;
&lt;p&gt;It&#39;s important to understand that these are nothing more than packages with an explicit name, placed at a convenient place - the top of a file with other imports - which immediately throw an error with a descriptive error message, at runtime.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;&#39;server-only&#39; cannot be imported from a Client Component module. It should only be used from a Server Component.&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// server-only index.js&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;This module cannot be imported from a Client Component module. &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;It should only be used from a Server Component.&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// server-only package.json&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token property&quot;&gt;&quot;exports&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;react-server&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./empty.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./index.js&quot;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see, these packages leverage &lt;strong&gt;package.json conditional exports&lt;/strong&gt; with the &lt;code&gt;react-server&lt;/code&gt; custom condition - supported by &lt;a href=&quot;https://nodejs.org/api/packages.html#exports&quot;&gt;Node.js&lt;/a&gt; (&lt;code&gt;node --conditions react-server server.js&lt;/code&gt;) &amp;amp; bundlers (such as &lt;a href=&quot;https://webpack.js.org/guides/package-exports/&quot;&gt;Webpack&lt;/a&gt; - with &lt;a href=&quot;https://webpack.js.org/configuration/resolve/#resolveconditionnames&quot;&gt;&lt;code&gt;resolve.conditionNames&lt;/code&gt;&lt;/a&gt;) to inject either the throwing module, or an empty &amp;quot;no-op&amp;quot; module, depending on the consumer environment.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; a potential alternative, would have been to use the &lt;code&gt;default: null&lt;/code&gt; target, which would have rendered the package impossible to import from an environment that does not satisfy the &lt;code&gt;react-server&lt;/code&gt; condition, causing an error at build time, or at runtime if there&#39;s no build step, and even possibly surfacing right in the developer&#39;s code editor thanks to static analysis with TypeScript for example.&lt;br&gt;
Although this alternative seems to be superior in every aspect to me, I haven&#39;t tested it so it&#39;s only theoritical.&lt;br&gt;
I am not aware of whether or not this alternative has been considered by the React Team, or if it did, why it wasn&#39;t chosen.&lt;/p&gt;
&lt;p&gt;If custom resolution conditions such as &lt;code&gt;react-server&lt;/code&gt; don&#39;t really work for you, or if you want to go further, rather than just throwing an error at runtime - which can be overlooked in some scenarios, and, from a productivity standpoint, potentially occurs too late in the developer&#39;s workflow, incurring an avoidable loss of productivity - it&#39;s a good idea to, like &lt;a href=&quot;https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack-config.ts&quot;&gt;Next.js does&lt;/a&gt;, error at build time at the bundler level, which is guaranteed to be more reliable (and still relying on the error being thrown at runtime as a safeguard), while also happenning much earlier in the process.&lt;br&gt;
This however assumes bundling for the target environment &amp;amp; requires additional processing &amp;amp; configuration, which of course, come at a cost, however relatively small.&lt;/p&gt;
&lt;h3 id=&quot;react-taint-apis&quot;&gt;React taint APIs &lt;a class=&quot;direct-link&quot; href=&quot;#react-taint-apis&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We&#39;ve mentioned earlier that &lt;a href=&quot;https://react.dev/reference/react/use-client#passing-props-from-server-to-client-components&quot;&gt;Server Components can pass props to Client Components (React docs)&lt;/a&gt;.&lt;br&gt;
Simply put, React Taint APIs allow you to “taint” or mark JavaScript values &amp;amp; objects that &lt;strong&gt;must not be passed&lt;/strong&gt; from the server to client, either by being passed from a Server Component to a Client component - in other words: which may not be serialized by React Server serialization APIs.&lt;br&gt;
I haven&#39;t had the occasion to personally try them out &amp;amp; research them further, but these APIs are without a doubt primordial to handle secrets with React Server features, and should be used in conjunction with previously mentioned &lt;code&gt;server-only&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Official React docs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://react.dev/reference/react/experimental_taintUniqueValue&quot;&gt;experimental_taintUniqueValue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://react.dev/reference/react/experimental_taintObjectReference&quot;&gt;experimental_taintObjectReference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Facebook/react package source code for the APIs mentioned above, on GitHub:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/main/packages/react/src/ReactTaint.js&quot;&gt;React Taint APIs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;react-server-%26-client-actions&quot;&gt;React Server &amp;amp; Client Actions &lt;a class=&quot;direct-link&quot; href=&quot;#react-server-%26-client-actions&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;announcements&quot;&gt;Announcements &lt;a class=&quot;direct-link&quot; href=&quot;#announcements&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;React Server &amp;amp; Client Actions&lt;/strong&gt; were &lt;a href=&quot;https://twitter.com/reactjs/status/1716573234160967762&quot;&gt;announced on October 23rd 2023&lt;/a&gt; to be available in &lt;a href=&quot;https://react.dev/community/versioning-policy#canary-channel&quot;&gt;React Canary releases&lt;/a&gt;, starting from &lt;a href=&quot;https://github.com/facebook/react/blob/main/CHANGELOG-canary.md#october-5-2023-1830-canary-546178f91-20231005&quot;&gt;October 5, 2023 (18.3.0-canary-546178f91-20231005)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Three days later, &lt;a href=&quot;https://twitter.com/nextjs/status/1717596665690091542&quot;&gt;Next.js announced on October 26th 2023 in Next.js 14&lt;/a&gt; &lt;a href=&quot;https://nextjs.org/blog/next-14#server-actions-stable&quot;&gt;“Server Actions (stable)”&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;ecosystem&quot;&gt;Ecosystem &lt;a class=&quot;direct-link&quot; href=&quot;#ecosystem&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This means the React Team considers these features frameworks, libraries (and the rest of the relevant ecosystem) can now adopt these features.&lt;br&gt;
At the time of writing and to my knowledge, these features are for the most part, only adopted by &lt;strong&gt;Next.js&lt;/strong&gt;.&lt;br&gt;
The &lt;strong&gt;Remix&lt;/strong&gt; React framework, has had a custom, somewhat similar feature to &lt;em&gt;Server Actions&lt;/em&gt; for some time with &lt;strong&gt;Remix Actions&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;philosophy&quot;&gt;Philosophy &lt;a class=&quot;direct-link&quot; href=&quot;#philosophy&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;React Server &amp;amp; Client actions are inscribed in a dynamic from the React Team to provide efficient APIs for form handling, mutations, data fetching &amp;amp; &lt;strong&gt;reducing client-side JavaScript bundle size&lt;/strong&gt;, promoting a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement&quot;&gt;Progressive Enhancement&lt;/a&gt; design philosophy with &lt;abbr title=&quot;Server-side Rendering&quot;&gt;SSR&lt;/abbr&gt;.&lt;/p&gt;
&lt;h2 id=&quot;thanks-for-reading!&quot;&gt;Thanks for reading! &lt;a class=&quot;direct-link&quot; href=&quot;#thanks-for-reading!&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you enjoyed this blog post, please feel free to share it and let me know on &lt;a href=&quot;https://twitter.com/tpillard&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://hachyderm.io/@tpillard&quot;&gt;Mastodon&lt;/a&gt;, don&#39;t hesitate to take a look at &lt;a href=&quot;https://timtech.blog/about/&quot;&gt;my about page&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;Further content may be added in the future, clarifications &amp;amp; corrections as well if needed.&lt;br&gt;
Follow-up blog posts covering experimental or modern React features should be added in the future.&lt;br&gt;
Clarifications &amp;amp; corrections may be added as well if needed - please let me know, feedback &amp;amp; discussions are welcome!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>TypeScript Legacy Experimental Decorators with Type Metadata in 2023</title>
		<link href="https://timtech.blog/posts/transform-typescript-legacy-decorators-vite-swc-plugin/"/>
		<updated>2023-10-14T00:00:00+00:00</updated>
		<id>https://timtech.blog/posts/transform-typescript-legacy-decorators-vite-swc-plugin/</id>
		<content type="html">&lt;img src=&quot;https://timtech.blog/img/benchmark-typescript-decorators-compilation-tsc-vs-vite-swc.webp&quot; width=&quot;640&quot; alt=&quot;Screenshot of a benchmark where Vite + SWC is 2.77 times faster than the TypeScript compiler&quot;&gt;
&lt;h2 id=&quot;tl%3Bdr&quot;&gt;TL;DR &lt;a class=&quot;direct-link&quot; href=&quot;#tl%3Bdr&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Just use Vite” (+ SWC)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vitejs.dev/&quot;&gt;https://vitejs.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ziir/vite-plugin-swc-transform&quot;&gt;https://github.com/ziir/vite-plugin-swc-transform&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;npm i --save-dev vite vite-plugin-swc-transform
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; defineConfig &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vite&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; swc &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vite-plugin-swc-transform&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;defineConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  plugins&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token function&quot;&gt;swc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;      swcOptions&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;        jsc&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;          target&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ES2021&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;          transform&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;            legacyDecorator&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;            decoratorMetadata&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;          &lt;span class=&quot;token comment&quot;&gt;// externalHelpers: true,&lt;/span&gt;&lt;br&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“kthxbye”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problem&quot;&gt;Problem &lt;a class=&quot;direct-link&quot; href=&quot;#problem&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I &lt;em&gt;need&lt;/em&gt; to compile TypeScript code leveraging &lt;strong&gt;TypeScript Legacy / Experimental Decorators with Type Metadata&lt;/strong&gt;.&lt;br&gt;
&lt;em&gt;I also need&lt;/em&gt; this compilation to be reasonably fast.&lt;br&gt;
And then, &lt;em&gt;I really want&lt;/em&gt; this compilation to be identical, as much as possible, between automated (unit &amp;amp; integration) &amp;amp; production.&lt;/p&gt;
&lt;h2 id=&quot;the-old-ways&quot;&gt;The Old Ways &lt;a class=&quot;direct-link&quot; href=&quot;#the-old-ways&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So far, my current setup involves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;jest&lt;/code&gt; framework for automated tests&lt;/li&gt;
&lt;li&gt;&lt;code&gt;babel-jest&lt;/code&gt;, the default Jest transformer, with a custom &lt;a href=&quot;https://babeljs.io/&quot;&gt;Babel&lt;/a&gt; preset including &lt;a href=&quot;https://babeljs.io/docs/babel-plugin-proposal-decorators&quot;&gt;@babel/plugin-proposal-decorators&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata&quot;&gt;babel-plugin-transform-typescript-metadata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tsc&lt;/code&gt;, the TypeScript compiler to transpile the code for production for an ES2021 browser target, using &lt;code&gt;--experimentalDecorators&lt;/code&gt; &amp;amp; &lt;code&gt;--emitDecoratorMetadata&lt;/code&gt; flags&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Bonus:&lt;/strong&gt; leveraging the &lt;code&gt;importHelpers&lt;/code&gt; &lt;code&gt;tsconfig.json&lt;/code&gt; flag &amp;amp; &lt;a href=&quot;https://github.com/Microsoft/tslib&quot;&gt;tslib&lt;/a&gt; to optimize TypeScript compilation output with &lt;code&gt;tsc&lt;/code&gt; &amp;amp; final JavaScript bundle size by reducing duplication of TypeScript runtime helpers - which in the case of &lt;strong&gt;legacy decorators &amp;amp; type metadata&lt;/strong&gt;, quickly add up to hundreds of kilobytes of pure, unnecessary bloat.&lt;/p&gt;
&lt;p&gt;The above works reasonably well, both in the context of automated testing (tens of developers) &amp;amp; production (hundreds of thousands of end-users).&lt;/p&gt;
&lt;p&gt;But as you can see, there are two problems with this current setup:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The compilation is &lt;strong&gt;slow enough&lt;/strong&gt; to:
&lt;ul&gt;
&lt;li&gt;be frustrating in many developer scenarios&lt;/li&gt;
&lt;li&gt;incur significant infrastructure costs for building packages &amp;amp; applications at this scale&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Slightly different transforms are used by different compilers in automated testing &amp;amp; production build:
&lt;ul&gt;
&lt;li&gt;potentially leading to subtle bugs&lt;/li&gt;
&lt;li&gt;overcomplicating the overall setup&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;why-not-compile-for-production-using-babel%3F&quot;&gt;Why not compile for production using Babel? &lt;a class=&quot;direct-link&quot; href=&quot;#why-not-compile-for-production-using-babel%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Yes. Using &lt;em&gt;Babel&lt;/em&gt; instead of &lt;em&gt;tsc&lt;/em&gt; for the production code compilation would improve the current situation in regard to the two problems mentioned above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Babel is slightly faster than tsc&lt;/li&gt;
&lt;li&gt;Babel &amp;amp; popular Babel plugins are often considered &lt;em&gt;the source of truth&lt;/em&gt; when it comes to compile transforms correctness&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;But&lt;/strong&gt;, Babel&#39;s rich plugin ecosystem &amp;amp; fine-grained transforms being its most important strengths, they&#39;re also its biggest weakness in that, they make, by nature, Babel more difficult to correctly configure &amp;amp; maintain over time.&lt;/p&gt;
&lt;p&gt;That is the main reason why I couldn&#39;t convince my peers to use Babel over tsc for production code compilation of a certain kind of library packages in early 2022.&lt;br&gt;
As a result, production code compilation with Babel did not make the cut to &lt;a href=&quot;https://github.com/ziir/ts-package-base&quot;&gt;ts-package-base&lt;/a&gt;, the first iteration of my TypeScript / Decorators / Metadata / React library package setup design with dual CJS/ESM compilation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; To this day, Babel remains my personal favourite JavaScript compiler.&lt;/p&gt;
&lt;h2 id=&quot;times-have-changed%2C-expectations-too&quot;&gt;Times have changed, expectations too &lt;a class=&quot;direct-link&quot; href=&quot;#times-have-changed%2C-expectations-too&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As sad as it may be, &lt;em&gt;Babel&lt;/em&gt; &amp;amp; &lt;em&gt;tsc&lt;/em&gt; are not longer the JavaScript compilers of choice in modern projects.&lt;/p&gt;
&lt;p&gt;The lines between a runtime, compiler, bundler &amp;amp; minimizer have been blurred by a new generation of tools and their combination, such as &lt;a href=&quot;https://esbuild.github.io/&quot;&gt;esbuild&lt;/a&gt;, &lt;a href=&quot;https://swc.rs/&quot;&gt;SWC&lt;/a&gt;, &lt;a href=&quot;https://tsup.egoist.dev/&quot;&gt;tsup&lt;/a&gt;, &lt;a href=&quot;https://vite.dev/&quot;&gt;Vite&lt;/a&gt; or even &lt;a href=&quot;https://bun.sh/&quot;&gt;Bun&lt;/a&gt; and more..&lt;/p&gt;
&lt;p&gt;These next-gen tools are all powerered or super-charged, in one way or another, by the arcane power of compiled languages such as Go, Rust or Zig, offering build performance unparalleled in the JavaScript world.&lt;/p&gt;
&lt;p&gt;Although they can, occasionally &amp;amp; to some degree, lack the maturity, correctness, ecosystem or functionality offered by their classic counterparts such as Webpack &amp;amp; Babel, there&#39;s also been a perception shift in the JavaScript community.&lt;br&gt;
Whereas a few years ago, Webpack &amp;amp; Babel were &lt;em&gt;the tools we loved to hate&lt;/em&gt;, next-gen tooling is &lt;strong&gt;hype&lt;/strong&gt;, thanks to, in some cases, funding, marketing, dedicated conferences, polished communication &amp;amp; integration in popular / hyped web frameworks.&lt;/p&gt;
&lt;p&gt;In conclusion: the classic tooling simply isn&#39;t good enough anymore, not necessarily in absolute, objective terms such as maturity, correctness, ecosystem or functionality, but, according to my own experience, in raw performance &amp;amp; developers perception.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; The next-gen tools I&#39;m mentioning here generally also have a remarkable focus on Developer Experience &amp;amp; sensible feature priorization according to popular use cases, which of course also contributes to their success.&lt;br&gt;
There is also a multitude of other factors explaining the fall or rise in popularity of these tools, whether they be considered as classic or next-gen.&lt;/p&gt;
&lt;h2 id=&quot;anyway&quot;&gt;Anyway &lt;a class=&quot;direct-link&quot; href=&quot;#anyway&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s get back to our &lt;a href=&quot;#problem&quot;&gt;initial problem statement&lt;/a&gt;, after a quick re-introduction to &lt;strong&gt;TypeScript Decorators &amp;amp; Metadata&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;typescript-legacy-%2F-experimental-%2F-stage-2-decorators-(experimentaldecorators)&quot;&gt;TypeScript Legacy / Experimental / Stage 2 Decorators (experimentalDecorators) &lt;a class=&quot;direct-link&quot; href=&quot;#typescript-legacy-%2F-experimental-%2F-stage-2-decorators-(experimentaldecorators)&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/decorators.html&quot;&gt;TypeScript Legacy / Experimental / Stage 2 Decorators&lt;/a&gt; are a natural evolution of TypeScript Classes.&lt;br&gt;
Composed &amp;amp; applied to classes, class accessors, method &amp;amp; method parameters, they are commonly used for performing validation, transformation, augmentation, proxying or dependency injection, for which they&#39;re notoriously used with &lt;a href=&quot;https://angular.io/guide/dependency-injection&quot;&gt;Angular&lt;/a&gt;, &lt;a href=&quot;https://docs.nestjs.com/fundamentals/custom-providers&quot;&gt;Nest&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://typeorm.io/&quot;&gt;TypeORM&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since their introduction in TypeScript, &lt;strong&gt;Legacy / Experimental / Stage 2 Decorators&lt;/strong&gt; support can be enabled through the &lt;code&gt;--experimentalDecorators&lt;/code&gt; flag (&lt;code&gt;experimentalDecorators&lt;/code&gt; in &lt;code&gt;tsconfig.json&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; see also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tc39/proposal-decorators&quot;&gt;current Stage 3 TC39 Decorators Proposal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#decorators&quot;&gt;TypeScript 5 Decorators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;decorators-type-metadata-(emitdecoratormetadata-%2F-reflect.metadata-%2F-reflect-metadata)&quot;&gt;Decorators Type Metadata (emitDecoratorMetadata / Reflect.metadata / reflect-metadata) &lt;a class=&quot;direct-link&quot; href=&quot;#decorators-type-metadata-(emitdecoratormetadata-%2F-reflect.metadata-%2F-reflect-metadata)&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://rbuckton.github.io/reflect-metadata/&quot;&gt;Metadata API Proposal&lt;/a&gt; specifies how to inject metadata to classes &amp;amp; objects, primarily through decorators (&amp;quot;annotations&amp;quot;), as well as reading this metadata through &lt;a href=&quot;https://en.wikipedia.org/wiki/Reflection_(computer_programming)&quot;&gt;reflection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/decorators.html#metadata&quot;&gt;TypeScript&#39;s Decorators Type Metadata&lt;/a&gt; in particular, allows to inject &lt;strong&gt;design-time&lt;/strong&gt; types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;design:type&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;design:paramtypes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;design:returntype&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It relies on the &lt;a href=&quot;https://github.com/rbuckton/reflect-metadata&quot;&gt;experimental metadata API&lt;/a&gt;, also know as &lt;code&gt;Reflect.metadata&lt;/code&gt; &amp;amp; for which the &lt;code&gt;reflect-metadata&lt;/code&gt; npm package provides a &lt;em&gt;shim&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In TypeScript, experimental decorators type metadata support &amp;amp; transforms are available through the &lt;a href=&quot;https://www.typescriptlang.org/tsconfig/emitDecoratorMetadata.html&quot;&gt;&lt;code&gt;--emitDecoratorMetadata&lt;/code&gt; flag, (&lt;code&gt;emitDecoratorMetadata&lt;/code&gt; in &lt;code&gt;tsconfig.json&lt;/code&gt;)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; see also &lt;a href=&quot;https://rbuckton.github.io/reflect-metadata/&quot;&gt;detailed ECMAScript Metadata Proposal&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;TypeScript, putting the Java back in JavaScript&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;vite%3F&quot;&gt;Vite? &lt;a class=&quot;direct-link&quot; href=&quot;#vite%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Yes.&lt;/p&gt;
&lt;h2 id=&quot;vitest%3F&quot;&gt;Vitest? &lt;a class=&quot;direct-link&quot; href=&quot;#vitest%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Also yes.&lt;/p&gt;
&lt;h2 id=&quot;typescript-legacy-experimental-decorators-with-type-metadata-with-vite%3F&quot;&gt;TypeScript Legacy Experimental Decorators with Type Metadata with Vite? &lt;a class=&quot;direct-link&quot; href=&quot;#typescript-legacy-experimental-decorators-with-type-metadata-with-vite%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt;&lt;br&gt;
Or at least, not by default.&lt;br&gt;
&lt;strong&gt;Vite&lt;/strong&gt; uses the &lt;a href=&quot;https://esbuild.github.io/&quot;&gt;esbuild&lt;/a&gt; transformer / compiler / bundler / minimizer by default, but unfortunately &lt;strong&gt;esbuild does not support emitting decorators metadata&lt;/strong&gt;.&lt;br&gt;
Therefore, we need to use a different JavaScript transformer / compiler.&lt;/p&gt;
&lt;h2 id=&quot;the-best-compiler-for-typescript-legacy-experimental-decorators-with-type-metadata%3F&quot;&gt;The best compiler for TypeScript Legacy Experimental Decorators with Type Metadata? &lt;a class=&quot;direct-link&quot; href=&quot;#the-best-compiler-for-typescript-legacy-experimental-decorators-with-type-metadata%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;ve previously mentioned that &lt;strong&gt;TypeScript / tsc&lt;/strong&gt; &amp;amp; Babel classic compilers support transforming both features, either behind flags, or through plugins, both of which are used in my current production setup.&lt;/p&gt;
&lt;p&gt;Surely there must be a next-gen compiler which supports those features as well, right? right?&lt;/p&gt;
&lt;p&gt;According to my research, &lt;a href=&quot;https://swc.rs/&quot;&gt;SWC&lt;/a&gt; is the only next-gen compiler supporting &lt;code&gt;legacyDecorator&lt;/code&gt; &amp;amp; &lt;code&gt;emitDecoratorMetadata&lt;/code&gt; at the moment.&lt;br&gt;
Furthermore, SWC also has a &lt;code&gt;externalHelpers&lt;/code&gt; option, similar to TypeScript&#39;s &lt;code&gt;importHelpers&lt;/code&gt; / &lt;code&gt;tslib&lt;/code&gt;, it allows re-using injected helper code by relying on helpers code from a &lt;code&gt;swc/helpers&lt;/code&gt; package instead of inlining helpers, which is invaluable to limit bundle size impact.&lt;br&gt;
But wait... it gets better!&lt;br&gt;
Indeed, &lt;a href=&quot;https://www.npmjs.com/package/@swc/helpers&quot;&gt;@swc/helpers&lt;/a&gt; actually leverage&#39;s &lt;code&gt;tslib&lt;/code&gt;&#39;s own helpers for decorator &amp;amp; metadata helpers!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/swc-project/swc/blob/main/packages/helpers/esm/_ts_decorate.js&quot;&gt;swc/packages/helpers/esm/_ts_decorate.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/swc-project/swc/blob/main/packages/helpers/esm/_ts_metadata.js&quot;&gt;swc/packages/helpers/esm/_ts_metadata.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And that&#39;s absolutely splendid for us!&lt;br&gt;
Since our production code is currently compiled with &lt;code&gt;typescript&lt;/code&gt; / &lt;code&gt;tsc&lt;/code&gt; + &lt;code&gt;tslib&lt;/code&gt;, using &lt;strong&gt;SWC&lt;/strong&gt; to compile our &lt;strong&gt;TypeScript Decorators &amp;amp; Metadata&lt;/strong&gt; code is &lt;strong&gt;guaranteed&lt;/strong&gt; to produce identical output!&lt;/p&gt;
&lt;p&gt;However, it&#39;s important to note that the rest of the transforms incurred by TypeScript may be implemented differently by SWC and can still be subject to subtle bugs.&lt;/p&gt;
&lt;h3 id=&quot;vite-%2B-swc%3F&quot;&gt;Vite + SWC? &lt;a class=&quot;direct-link&quot; href=&quot;#vite-%2B-swc%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple plugins exist for handing over transform responsability to &lt;strong&gt;SWC in Vite&lt;/strong&gt;, to name a few:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/@vitejs/plugin-react-swc&quot;&gt;@vitejs/plugin-react-swc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/unplugin-swc&quot;&gt;unplugin-swc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They all seemed to work, as far as I could tell from my limited testing.&lt;br&gt;
But diving at the implementation &amp;amp; documentation for each of them, it appeared they all covered much larger use cases (React Refresh, Rollup, minification ...) than my own, sometimes with significant overhead, complexity or opinionated API.&lt;/p&gt;
&lt;h3 id=&quot;vite-plugin-swc-transform&quot;&gt;vite-plugin-swc-transform &lt;a class=&quot;direct-link&quot; href=&quot;#vite-plugin-swc-transform&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&#39;m probably already paying an overhead cost by using Vite instead of running SWC directly for reasons explained above and then some, and I wanted to use a &lt;strong&gt;SWC plugin for Vite&lt;/strong&gt; with the most minimal &amp;amp; transparent API surface.&lt;/p&gt;
&lt;p&gt;Therefore, I decided to implement my own simple &lt;strong&gt;Vite plugin for transforming TypeScript Decorators + Metadata source files with SWC&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&quot;https://github.com/ziir/vite-plugin-swc-transform&quot;&gt;vite-plugin-swc-transform on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Please note this plugin is not necessarily meant as a replacement of alternative plugins.&lt;br&gt;
It is rather intended as a way to address my own use cases efficiently.&lt;/p&gt;
&lt;p&gt;However, please feel free to open an issue on GitHub if you have ideas on how it could be improved, or additional use cases you&#39;d like it to support.&lt;/p&gt;
&lt;h2 id=&quot;tsc-vs-vite-%2B-swc&quot;&gt;tsc vs Vite + SWC &lt;a class=&quot;direct-link&quot; href=&quot;#tsc-vs-vite-%2B-swc&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For comparing &lt;strong&gt;tsc&lt;/strong&gt; to &lt;strong&gt;Vite + SWC&lt;/strong&gt;, we&#39;ll be focusing on a single case study matching my main current use case:&lt;br&gt;
Building a typical library package for production as ES2021 target &lt;abbr title=&quot;EcmaScript Modules&quot;&gt;ESM&lt;/abbr&gt;, composed of 124 TypeScript modules, a fair amount of which leverage TypeScript Legacy Decorators &amp;amp; Metadata, intended to run primarily in a browser after being bundled in a web project.&lt;/p&gt;
&lt;h3 id=&quot;speed%3A-build-performance-benchmark&quot;&gt;Speed: build performance benchmark &lt;a class=&quot;direct-link&quot; href=&quot;#speed%3A-build-performance-benchmark&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The benchmark is running on an ~old Intel Macbook Pro.&lt;br&gt;
Both builds output &lt;strong&gt;ESM for an ES2021 target&lt;/strong&gt;.&lt;br&gt;
The &lt;code&gt;tsconfig.json&lt;/code&gt; file used for the &lt;code&gt;tsc&lt;/code&gt; build is reasonably optimized for build performance with minimal type-checking.&lt;br&gt;
Vite is configured to not attempt bundling nor minifying, and preserve the source directory structure in the output directory.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Benchmark 1: pnpm run build:esm:tsc
  Time (mean ± σ):      3.733 s ±  0.028 s    [User: 6.339 s, System: 0.429 s]
  Range (min … max):    3.696 s …  3.799 s    10 runs

Benchmark 2: pnpm run build:esm:vite-swc
  Time (mean ± σ):      1.347 s ±  0.031 s    [User: 1.650 s, System: 0.309 s]
  Range (min … max):    1.324 s …  1.432 s    10 runs

Summary
  pnpm run build:esm:vite-swc ran 2.77 ± 0.07 times faster than pnpm run build:esm:tsc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Vite + SWC is ~2.77 times faster than &lt;code&gt;tsc&lt;/code&gt; in this configuration.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;correctness%3A-compiled-javascript-output-review&quot;&gt;Correctness: compiled JavaScript output review &lt;a class=&quot;direct-link&quot; href=&quot;#correctness%3A-compiled-javascript-output-review&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When evaluating or switching JavaScript compilers, simply relying on an existing automated tests suite or manual testing is, in my experience, generally not enough.&lt;br&gt;
It&#39;s important to also review the compiled outputs, look for differences &amp;amp; identify potential issues, opportunities for improvement.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ wc -l esm-es2021-tsc-vs-vite-swc.pretty.patch
&amp;gt; 6826
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;swc-adds-.js-file-extension-to-relative-module-imports&quot;&gt;SWC adds &lt;code&gt;.js&lt;/code&gt; file extension to relative module imports &lt;a class=&quot;direct-link&quot; href=&quot;#swc-adds-.js-file-extension-to-relative-module-imports&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The first &amp;amp; omnipresent difference in compilation output between &lt;code&gt;tsc&lt;/code&gt; &amp;amp; &lt;strong&gt;Vite + SWC&lt;/strong&gt; is SWC appending the &lt;code&gt;.js&lt;/code&gt; file extension to relative module imports.&lt;/p&gt;
&lt;p&gt;Our example package is advertised as &lt;strong&gt;ESM&lt;/strong&gt; with &lt;code&gt;type: &#39;module&#39;&lt;/code&gt; in its &lt;code&gt;package.json&lt;/code&gt; file &amp;amp; the input source code is composed of &lt;code&gt;.ts&lt;/code&gt; files which use &lt;strong&gt;relative, extension-less imports&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This library package uses &lt;code&gt;typescript@5.2&lt;/code&gt;, is configured with &lt;code&gt;module: &#39;esnext&#39;&lt;/code&gt; + &lt;code&gt;moduleResolution: &#39;bundler&#39;&lt;/code&gt; compiler options in &lt;code&gt;tsconfig.json&lt;/code&gt; and is primarily intended to be &lt;strong&gt;consumed by a bundler&lt;/strong&gt;, for building a web app &lt;strong&gt;running in the browser&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Extract from the actual diff between &lt;strong&gt;tsc &amp;amp; Vite + SWC outputs&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isModuleImplementationDefinition &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;../dependency-injection/module.types&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/del&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; isModuleImplementationDefinition &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;../dependency-injection/module.types.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In our case, it&#39;s a safe change, and arguably a good one.&lt;/p&gt;
&lt;p&gt;Indeed, bundlers &amp;amp; runtimes use &lt;strong&gt;different module resolution algorithms&lt;/strong&gt; to be able to resolve actual modules from an import statement.&lt;br&gt;
These algorithms can behave slightly differently from one to another, and by appending &lt;code&gt;.js&lt;/code&gt; file extension to relative module imports, &lt;code&gt;SWC&lt;/code&gt; clears the ambiguity of the possible files that should match a given compiled import.&lt;/p&gt;
&lt;p&gt;This also results in a &lt;strong&gt;faster &amp;amp; more efficient module resolution&lt;/strong&gt; process, because the algorithm doesn&#39;t have to check for files matching the import specifier, with multiple possible file extensions.&lt;/p&gt;
&lt;hr&gt;
&lt;h5 id=&quot;about-typescript-module-resolution%2C-module-formats-%26-compilation-targets&quot;&gt;About TypeScript module resolution, module formats &amp;amp; compilation targets &lt;a class=&quot;direct-link&quot; href=&quot;#about-typescript-module-resolution%2C-module-formats-%26-compilation-targets&quot;&gt;#&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;With &lt;code&gt;tsc&lt;/code&gt;, &lt;strong&gt;module specifiers are not transformed&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If your project targets Node.js &amp;amp; compiles to ESM though, &lt;code&gt;module: &#39;node16&#39;&lt;/code&gt; (or &lt;code&gt;&#39;nodenext&lt;/code&gt;) &amp;amp; &lt;code&gt;moduleResolution: &#39;node16&#39;&lt;/code&gt; (or &lt;code&gt;nodenext&lt;/code&gt;) is the only correct &lt;code&gt;tsconfig.json&lt;/code&gt; combination matching &lt;strong&gt;Node.js ES modules resolution algorithm&lt;/strong&gt;.&lt;br&gt;
In which case, you will be required by the TypeScript compiler to &lt;strong&gt;author relative module imports with their runtime specifier&lt;/strong&gt;, in other words, with their runtime extension, ie &lt;code&gt;.js&lt;/code&gt; - but that doesn&#39;t apply if you use &lt;code&gt;moduleResolution: &#39;bundler&#39;&lt;/code&gt; (which is our case here) or compile to &lt;abbr title=&quot;CommonJS&quot;&gt;CJS&lt;/abbr&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/modules/theory.html#module-resolution&quot;&gt;Learn more about TypeScript Module Theory &amp;amp; Module Resolution&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;swc-%26-tsc-set-class-properties-differently%3A-usedefineforclassfields&quot;&gt;SWC &amp;amp; tsc set class properties differently: useDefineForClassFields &lt;a class=&quot;direct-link&quot; href=&quot;#swc-%26-tsc-set-class-properties-differently%3A-usedefineforclassfields&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Note: to be continued...&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;to-be-continued...&quot;&gt;To be continued... &lt;a class=&quot;direct-link&quot; href=&quot;#to-be-continued...&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This blog post only covers one, although crucial, aspect of my current &lt;em&gt;quest&lt;/em&gt;, quest which I hope will result in a succesful &amp;amp; impactful migration.&lt;br&gt;
Follow-up blog posts should be added in the future.&lt;br&gt;
Clarifications &amp;amp; corrections may be added as well if needed.&lt;/p&gt;
&lt;h2 id=&quot;thanks-for-reading!&quot;&gt;Thanks for reading! &lt;a class=&quot;direct-link&quot; href=&quot;#thanks-for-reading!&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you enjoyed this blog post, please feel free to share it and let me know on &lt;a href=&quot;https://twitter.com/tpillard&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://hachyderm.io/@tpillard&quot;&gt;Mastodon&lt;/a&gt;, don&#39;t hesitate to take a look at &lt;a href=&quot;https://timtech.blog/about/&quot;&gt;my about page&lt;/a&gt; as well.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>React memo is good actually</title>
		<link href="https://timtech.blog/posts/react-memo-is-good-actually/"/>
		<updated>2023-10-06T00:00:00+00:00</updated>
		<id>https://timtech.blog/posts/react-memo-is-good-actually/</id>
		<content type="html">&lt;img src=&quot;https://timtech.blog/img/always-has-been-meme.webp&quot; alt=&quot;Wait React meme is good actually? Always has been&quot; width=&quot;480&quot;&gt;
&lt;h2 id=&quot;disclaimer&quot;&gt;Disclaimer &lt;a class=&quot;direct-link&quot; href=&quot;#disclaimer&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This blog post expresses my &lt;strong&gt;personal views&lt;/strong&gt; on a &lt;strong&gt;controversial, complex &amp;amp; ever evolving topic&lt;/strong&gt;, based on my personal experience.&lt;br&gt;
Your mileage may vary.&lt;/p&gt;
&lt;h2 id=&quot;memo%2C-usememo%2C-usecallback-for-performance-(%26-logic-correctness)&quot;&gt;memo, useMemo, useCallback for performance (&amp;amp; logic correctness) &lt;a class=&quot;direct-link&quot; href=&quot;#memo%2C-usememo%2C-usecallback-for-performance-(%26-logic-correctness)&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://react.dev/reference/react/memo&quot;&gt;React.memo&lt;/a&gt;, &lt;a href=&quot;https://react.dev/reference/react/useMemo&quot;&gt;React.useMemo&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://react.dev/reference/react/useCallback&quot;&gt;React.useCallback&lt;/a&gt;, respectively a &lt;abbr title=&quot;Higher Order Component&quot;&gt;HOC&lt;/abbr&gt; &amp;amp; performance hooks, are official APIs provided by the React library ~since React@16 (2018), commonly yet hesitantly used in React applications.&lt;br&gt;
They are notably used for improving application runtime &amp;amp; &lt;strong&gt;rendering performance&lt;/strong&gt;, and regarding &lt;strong&gt;React.useMemo &amp;amp; React.useCallback hooks&lt;/strong&gt;, also to &lt;strong&gt;ensure stability of non-primitive JavaScript values&lt;/strong&gt;, when such values are used as effect hooks, ie &lt;a href=&quot;https://react.dev/reference/react/useEffect&quot;&gt;React.useEffect&lt;/a&gt; dependencies.&lt;br&gt;
In which case, they also contribute to application logic correctness.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: if you&#39;re not familiar with these APIs, I can&#39;t recommend enough to read the excellent &lt;a href=&quot;https://react.dev/reference/react&quot;&gt;React API Reference&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;great-apis%2C-bad-reputation%2C-strong-positions&quot;&gt;Great APIs, bad reputation, strong positions &lt;a class=&quot;direct-link&quot; href=&quot;#great-apis%2C-bad-reputation%2C-strong-positions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since these they were introduced (and even before with &lt;strong&gt;React.PureComponent&lt;/strong&gt; &amp;amp; &lt;strong&gt;React.Component.shouldComponentUpdate&lt;/strong&gt;), &lt;strong&gt;React performance APIs&lt;/strong&gt; have, in my opinion, suffered time and again from bad press: countless incorrect, oriented, biased, dishonest articles, medium posts, tweets, code review comments, opinions &amp;amp; rants, describing the APIs as “&lt;em&gt;counter-productive, unnecessary, bad, evil&lt;/em&gt;” or even “&lt;em&gt;dangerous&lt;/em&gt;”.&lt;br&gt;
All with varying degrees of over-simplification, absolutes, subscribe buttons, links to YouTube channels, paid courses &amp;amp; workshops.&lt;/p&gt;
&lt;p&gt;Thankfully, most of this content is old now and it&#39;s not brought up nearly as often as it used to a few years ago.&lt;br&gt;
Unfortunately, they still rank very well on search engines and regularly make their way into colorful engagement-bait info-graphics on X dot com.&lt;/p&gt;
&lt;p&gt;Of course, some actually great, nuanced &amp;amp; technically correct content exists covering in-depth &lt;strong&gt;React Rendering Behavior&lt;/strong&gt; or alternative &lt;em&gt;ways to improve React rendering performance&lt;/em&gt; - it&#39;s not necessarily the easiest to find, but not too difficult either.&lt;/p&gt;
&lt;p&gt;But the problem is, bad press &amp;amp; demonization of APIs: it sticks.&lt;br&gt;
Over the years (since what, 2017, 2018?) I have seen open source maintainers, tech leads, engineers, Senior, Staff+ alike, take very strong positions pushing back against the use of React performance APIs at work or in public, all in the name of “&lt;em&gt;readability, anti-fragility, performance, simplicity, convenience, consistency, dogma&lt;/em&gt;”, and more.&lt;/p&gt;
&lt;p&gt;All this with an outstanding immediate effect of leading to heated debates in code reviews, stalling pull requests, gatekeeping, drama, frustration, and too often as a result: a halt to efforts aiming to &lt;strong&gt;improve rendering performance&lt;/strong&gt; for the users.&lt;/p&gt;
&lt;h2 id=&quot;most-common-misconceptions&quot;&gt;Most Common Misconceptions &lt;a class=&quot;direct-link&quot; href=&quot;#most-common-misconceptions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let us review some of the most common misconceptions I&#39;ve come across over the years, which, I believe, are both a consequence &amp;amp; a catalyst of React performance APIs bad reputation &amp;amp; related difficulties mentioned previously.&lt;/p&gt;
&lt;h3 id=&quot;1.-%E2%80%9Creact-is-so-fast-anyway%2C-react.memo-is-unnecessary%E2%80%9D&quot;&gt;1. “React is so fast anyway, React.memo is unnecessary” &lt;a class=&quot;direct-link&quot; href=&quot;#1.-%E2%80%9Creact-is-so-fast-anyway%2C-react.memo-is-unnecessary%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;INCORRECT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Although yes, React is fast enough in most cases, there&#39;s a reason these React performance APIs exist in the first place: they fill in a gap in React&#39;s model and a gap in the ability of teams to maintain a code base in par with state of the art practices over time.&lt;/p&gt;
&lt;p&gt;Furthermore, the actual rendering performance of a client-side web application or &lt;abbr title=&quot;Single Page Application&quot;&gt;SPA&lt;/abbr&gt; is dependent on many factors beyond the underlying view rendering library being “fast”.&lt;br&gt;
These factors include the state of the code base, dependencies, use cases &amp;amp; functionalities, as well as external factors like the user&#39;s device or web browser.&lt;/p&gt;
&lt;p&gt;Accordingly, rendering performance issues in React projects are extremely common, and can most of the time be mitigated or fully resolved with a combination of best practices, patterns, refactoring, re-architecture and tools, including &lt;strong&gt;React.memo&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;2.-%E2%80%9Creact.memo-is-counter-productive%E2%80%9D&quot;&gt;2. “React.memo is counter-productive” &lt;a class=&quot;direct-link&quot; href=&quot;#2.-%E2%80%9Creact.memo-is-counter-productive%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Also known as &lt;strong&gt;“React.memo&#39;s props shallow-equality check&#39;s overhead is detrimental to performance&lt;/strong&gt;”.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;INCORRECT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;React memoization in general &amp;amp; React.memo specifically can be counter-productive if it&#39;s not used correctly, ie: when used on a component that more often than not receives different props between renders, which will render memoization ineffective, while still incurring the cost of comparing previous memoized props with new props, (by default using a shallow-equal comparison).&lt;/p&gt;
&lt;p&gt;In other cases where React.memo is used correctly, and some re-renders of the memoized components are legitimate because their props are legitimately different across renders, then yes, &lt;code&gt;React.memo&lt;/code&gt; incurs an unnecessary overhead cost, mostly through its &lt;code&gt;compare&lt;/code&gt; function - &lt;a href=&quot;https://github.com/facebook/react/blob/85c2b519b54269811002d26f4f711809ef68f123/packages/shared/shallowEqual.js#L18&quot;&gt;React&#39;s shallow equal comparison&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In any case, in real-life applications, &lt;strong&gt;React&#39;s shallow comparison&#39;s cost&lt;/strong&gt; is arguably negligible &amp;amp; highly unlikely to be more expensive than a prevented re-render of any non-trivial component.&lt;/p&gt;
&lt;h3 id=&quot;3.-%E2%80%9Creact.memo-doesn&#39;t-work-with-react-element-%2F-children-props%E2%80%9D&quot;&gt;3. “React.memo doesn&#39;t work with React element / children props” &lt;a class=&quot;direct-link&quot; href=&quot;#3.-%E2%80%9Creact.memo-doesn&#39;t-work-with-react-element-%2F-children-props%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;INCORRECT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Well, not &lt;em&gt;entirely&lt;/em&gt; incorrect, since React elements are commonly created using JSX, which is transformed to &lt;code&gt;React.createElement(...)&lt;/code&gt; calls (or equivalent) , always returning new object, then yes, naive passing of React elements as props to a memoized component will render its memoization ineffective.&lt;/p&gt;
&lt;p&gt;However, it won&#39;t be the case if you pass &lt;strong&gt;stable / constant React elements&lt;/strong&gt; - ie defined outside of the parent function component&#39;s scope or memoized with &lt;code&gt;React.useMemo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The former can be done automatically where applicable using &lt;a href=&quot;https://babeljs.io/docs/babel-plugin-transform-react-constant-elements.html&quot;&gt;babel-plugin-transform-react-constant-element&lt;/a&gt; or equivalent compiler transforms - although when dealing with stable props to be passed to a &lt;code&gt;React.memo&lt;/code&gt;&#39;d component, it&#39;s best to be explicit than to rely on an implicit compiler transform.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bonus&lt;/strong&gt;: the re-render of a &lt;strong&gt;stable&lt;/strong&gt; / &lt;strong&gt;constant&lt;/strong&gt; React element will be skipped by React, regardless of it being memoized with React.memo or not.&lt;br&gt;
This React behavior is also known as &lt;strong&gt;&amp;quot;same reference element optimization&amp;quot;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For instance, the following code renders the memoization of &lt;code&gt;&amp;lt;MemoizedLayoutComponent&amp;gt;&lt;/code&gt; inneffective:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MemoizedLayoutComponent&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SomeUIComponent&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MemoizedLayoutComponent&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But the following - whether done manually as in this example, or automatically via &lt;code&gt;babel-plugin-transform-react-constant-element&lt;/code&gt; - allows &lt;code&gt;&amp;lt;MemoizedLayoutComponent&amp;gt;&lt;/code&gt;&#39;s memoization to work as expected, and ensures our &lt;code&gt;&amp;lt;SomeUIComponent /&amp;gt;&lt;/code&gt; child component to never be re-rendered (other than through an update of its own state).&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; someUIElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SomeUIComponent&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MemoizedComponent&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;someUIElement&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MemoizedComponent&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; The following variant, using &lt;code&gt;React.useMemo&lt;/code&gt; on &lt;code&gt;&amp;lt;SomeUIComponent /&amp;gt;&lt;/code&gt; when dealing with some dynamic props, although less recommendable, also works - both &lt;code&gt;&amp;lt;SomeUIComponent&amp;gt;&lt;/code&gt; &amp;amp; &lt;code&gt;&amp;lt;MemoizedComponent&amp;gt;&lt;/code&gt; will be re-rendered if &lt;code&gt;dynamicProp&lt;/code&gt; changes (assuming a state update), but neither will ever be re-rendered otherwise:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dynamicProp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useDynamicProp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; someUIElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;useMemo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/mark&gt;&lt;br&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SomeUIComponent&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;staticProp&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;static&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;dynamicProp&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;dynamicProp&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dynamicProp&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/mark&gt;&lt;br&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MemoizedComponent&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;someUIElement&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MemoizedComponent&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;4.-%E2%80%9Creact.memo-is-too-fragile%E2%80%9D&quot;&gt;4. “React.memo is too fragile” &lt;a class=&quot;direct-link&quot; href=&quot;#4.-%E2%80%9Creact.memo-is-too-fragile%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;DISAGREE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;React.memo does have a weakness: in order to be effective, it requires the consumer of a memoized React component, to be aware that said React component has been wrapped by the &lt;code&gt;React.memo&lt;/code&gt; &lt;abbr title=&quot;Higher Order Component&quot;&gt;HOC&lt;/abbr&gt; and thus, that its props are expected to be stable for component memoization to be effective.&lt;/p&gt;
&lt;p&gt;Some argue that consumers of a React component shouldn&#39;t be aware of how said component is defined or exported, that it&#39;s an implementation detail.&lt;br&gt;
&lt;strong&gt;I disagree.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I believe, like any function, any API you didn&#39;t write yourself, you should refer to the documentation, JSDoc definition, better yet, also refer to the source of truth: the source code, tests, and even in more cases that I&#39;d like, compiler configuration &amp;amp; output!&lt;br&gt;
What if the underlying component uses some of the provided props as &lt;code&gt;React.useEffect()&lt;/code&gt; dependencies?&lt;/p&gt;
&lt;p&gt;Regardless, this weakness can be addressed in multiple ways, such as &lt;strong&gt;adopting &amp;amp; documenting a naming convention&lt;/strong&gt; within your team, &lt;strong&gt;indicating the memoized nature&lt;/strong&gt; of the exported component, ie:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; MemoizedList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;List&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another naming convention could be to convey the necessity for specific non-primitive value props to be referentially stable as much as possible:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stableData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;useMemo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stableData&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;stableData&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note: this example relies on React.useMemo with an empty dependency array just for demonstration purposes.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Alternatively, you can to &lt;strong&gt;shift the responsability&lt;/strong&gt; of wrapping the component to memoize with &lt;code&gt;React.memo&lt;/code&gt; by doing it, not in the file where the component is exported, but it in the file where the component is used:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; List &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; RawList &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./List&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; MemoizedList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;List&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useStableData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MemoizedList&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Additionally, &lt;a href=&quot;https://github.com/facebook/react/blob/85c2b519b54269811002d26f4f711809ef68f123/packages/react/src/ReactMemo.js#L14&quot;&gt;&lt;code&gt;React.memo()&lt;/code&gt; being a HOC&lt;/a&gt;, you &lt;em&gt;could&lt;/em&gt; create your own wrapper around it, so it can be leveraged in a &lt;strong&gt;declarative way&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Something along those lines for example:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; items &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MyMemo&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;List&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; I wouldn&#39;t recommend this, but it&#39;s possible.&lt;/p&gt;
&lt;p&gt;Finally, &lt;strong&gt;alternatives to React.memo&lt;/strong&gt; can be just as much fragile, in slightly different &amp;amp; subtle ways.&lt;br&gt;
Arguably, React.memo &amp;amp; React.useMemo can be helpful if you want to render your code more robust.&lt;/p&gt;
&lt;p&gt;Custom React Context Provider components for instance, are often used to provide both a getter &amp;amp; a setter to consumer components, encapsulating specific domain specific logic, and used in the application&#39;s entry-point component.&lt;br&gt;
We can carefuly write our Custom React &lt;code&gt;Context.Provider&lt;/code&gt; component in a way that doesn&#39;t make it necessary to use &lt;code&gt;React.memo&lt;/code&gt; on the &lt;code&gt;&amp;lt;Main /&amp;gt;&lt;/code&gt; component, assuming it renders an expensive subtree, and we can also avoid wrapping the provided value in &lt;code&gt;React.useMemo()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ThemeContext &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ThemeContextProvider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;theme&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setTheme&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dark&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; theme&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setTheme &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContext.Provider&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContext.Provider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContextProvider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Main&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContextProvider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; I would probably do this too in most cases.&lt;/p&gt;
&lt;p&gt;However, additional wrappers around or replacing an application&#39;s entry-point component over time are a reality, and any future changes in the code base introducing additional state updates in or above &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; will render these careful efforts in avoiding &lt;code&gt;React.memo&lt;/code&gt; &amp;amp; &lt;code&gt;React.useMemo&lt;/code&gt; counter-productive.&lt;/p&gt;
&lt;p&gt;Indeed, both &lt;code&gt;&amp;lt;Main /&amp;gt;&lt;/code&gt;, with its expensive subtree &amp;amp; &lt;code&gt;&amp;lt;ThemeContextProvider&amp;gt;&lt;/code&gt; will re-render, a new &lt;code&gt;value&lt;/code&gt; object created and then all &lt;code&gt;React.useContext(ThemeContext)&lt;/code&gt; consumers will be re-rendered, even if the &lt;code&gt;theme&lt;/code&gt; value hasn&#39;t changed.&lt;br&gt;
Although we could split our &lt;code&gt;&amp;lt;ThemeContextProvider&amp;gt;&lt;/code&gt; into a &lt;code&gt;&amp;lt;ThemeGetterContextProvider&amp;gt;&lt;/code&gt; &amp;amp; &lt;code&gt;&amp;lt;ThemeSetterContextProvider&amp;gt;&lt;/code&gt; to address this issue, we would lose the consolidation of our theme handling domain logic in a single component, introduce more friction in the code base &amp;amp; have to go through a refactor of all context consumers, potentially introducing risks.&lt;/p&gt;
&lt;p&gt;Whereas we &lt;em&gt;could&lt;/em&gt; have ensured the &lt;em&gt;robustness&lt;/em&gt; of both our &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; component, our &lt;code&gt;ThemeContextProvider&lt;/code&gt; component &amp;amp; consumers from the start with &lt;code&gt;React.memo&lt;/code&gt; &amp;amp; &lt;code&gt;React.useMemo&lt;/code&gt;.&lt;br&gt;
For the sake of demonstration:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ThemeContext &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ThemeContextProvider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;theme&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setTheme&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dark&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;useMemo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; theme&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setTheme &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;theme&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContext.Provider&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContext.Provider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; MemoizedMain &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Main&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContextProvider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MemoizedMain&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContextProvider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;  )&lt;br&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; I would do this in some cases.&lt;/p&gt;
&lt;p&gt;Or more explicitly:&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ThemeContext &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ThemeContextProvider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;theme&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setTheme&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dark&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;// Although currently this component is rendered exactly once,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;// we memoize the context value preemptively to ensure it will never cause&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;// unnecessary re-renders of its consumers, ie if this component becomes&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;// subject to updates from its parent component, such as if it&#39;s moved closer to its consumers&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;useMemo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; theme&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setTheme &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;theme&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContext.Provider&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContext.Provider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; MemoizedApp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContextProvider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Main&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;br&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThemeContextProvider&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;/**&lt;br&gt;   * The App component is our application entry-point.&lt;br&gt;   * and should only be rendered exactly once.&lt;br&gt;   **/&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;/* prevProps, newProps */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__DEV__&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Unexpected re-render of &amp;lt;App /&gt; entry-point&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt;: I would only do this in specific cases.&lt;/p&gt;
&lt;h3 id=&quot;5.-%E2%80%9Creact.memo-%2F-react.usememo-%2F-react.usecallback-are-signs-of-poor-architecture%E2%80%9D&quot;&gt;5. “React.memo / React.useMemo / React.useCallback are signs of poor architecture” &lt;a class=&quot;direct-link&quot; href=&quot;#5.-%E2%80%9Creact.memo-%2F-react.usememo-%2F-react.usecallback-are-signs-of-poor-architecture%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;INCORRECT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Occasionally, maybe, it depends.&lt;br&gt;
See &lt;a href=&quot;#6.-%E2%80%9Cthere-are-better-alternatives-to-react.memo-%2F-react.usememo-%2F-react.usecallback%E2%80%9D&quot;&gt;6. “There are better alternatives to React.memo / React.useMemo / React.useCallback”&lt;/a&gt;.&lt;br&gt;
But my point is, even when the use of these APIs make possible improvements apparent - that may or may not allow not to use these APIs in the first place, &lt;strong&gt;the use of React Performance APIs in itself, is perfectly valid&lt;/strong&gt;, at least pending the refactoring of the relevant code, which may or may not happen in the future, depending on a multitude of factors: complexity, resources, product pressure, etc.&lt;/p&gt;
&lt;h3 id=&quot;6.-%E2%80%9Cthere-are-better-alternatives-to-react.memo-%2F-react.usememo-%2F-react.usecallback%E2%80%9D&quot;&gt;6. “There are better alternatives to React.memo / React.useMemo / React.useCallback” &lt;a class=&quot;direct-link&quot; href=&quot;#6.-%E2%80%9Cthere-are-better-alternatives-to-react.memo-%2F-react.usememo-%2F-react.usecallback%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;SOMETIMES&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Known best practices, patterns such as &lt;strong&gt;keeping component state as local as possible&lt;/strong&gt; &amp;amp; &lt;strong&gt;lifting content up&lt;/strong&gt;, tools such as state containers, etc. can often have an outstanding effect on rendering performance and render some React.memo uses unnecessary.&lt;/p&gt;
&lt;p&gt;Effects with &lt;code&gt;React.useEffect&lt;/code&gt; can sometimes be written in a way that doesn&#39;t rely on non-primitive value dependencies, thus removing the need for &lt;code&gt;React.useMemo&lt;/code&gt; or &lt;code&gt;React.useCallback&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But in a lot of real world situations, these aren&#39;t enough, nor even the best choice depending on the project&#39;s context: for example, more often than it seems, using these APIs and opting into “inferior” patterns is a better trade-off than the re-architecture of an application, rewriting a lot existing of code.&lt;/p&gt;
&lt;h3 id=&quot;7.-%E2%80%9Creact.memo-%2F-react.usememo-%2F-react.usecallback-are-detrimental-to-readability-%26-maintainability%E2%80%9D&quot;&gt;7. “React.memo / React.useMemo / React.useCallback are detrimental to readability &amp;amp; maintainability” &lt;a class=&quot;direct-link&quot; href=&quot;#7.-%E2%80%9Creact.memo-%2F-react.usememo-%2F-react.usecallback-are-detrimental-to-readability-%26-maintainability%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;DISAGREE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If they&#39;re misused? Sure - and I&#39;m all for enforcing either using them correctly or not using them at all.&lt;/p&gt;
&lt;p&gt;But as soon as these APIs are used correctly, I find they actually improve one&#39;s understanding of the code upon reading, and practically convey or highlight important information.&lt;/p&gt;
&lt;p&gt;When I see &lt;code&gt;React.memo&lt;/code&gt; used in a code base that otherwise doesn&#39;t use it much, I don&#39;t read:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“This component is optimized.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I read:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“The components subtree in which this component is rendered, is maybe in the critical path, probably subject to unnecessary &amp;amp; potentially expensive re-renders relative to the other components in the code base.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When I see &lt;code&gt;React.memo&lt;/code&gt; used in a lot of places, I read:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“It&#39;s our philosophy that every component should be as efficient as possible.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Similarly, when I see &lt;code&gt;React.[useCallback/memo]&lt;/code&gt;, I read:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“It&#39;s important for this value to adhere to immutability principles because it&#39;s computationally heavy or because we need to keep a stable reference, according to the following dependencies.&lt;br&gt;
It&#39;s likely to be used by effects or other performance APIs.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;8.-%E2%80%9Cbut-%3Cauthority-figure%3E-said-not-to-use-these-apis!-(or-similar)%E2%80%9D&quot;&gt;8. “But &amp;lt;authority figure&amp;gt; said not to use these APIs! (or similar)” &lt;a class=&quot;direct-link&quot; href=&quot;#8.-%E2%80%9Cbut-%3Cauthority-figure%3E-said-not-to-use-these-apis!-(or-similar)%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;INCORRECT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First of all they probably didn&#39;t say or mean that litterally.&lt;br&gt;
Or maybe they did, but regardless - and however appreciative we can be for their contributions, recommendations, etc:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;they don&#39;t write the code: we do.&lt;/li&gt;
&lt;li&gt;they&#39;re not the ones who pay the price of bugs &amp;amp; inaction: our users do, and ultimately, we do too.&lt;/li&gt;
&lt;li&gt;it&#39;s up to us, not them.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;9.-%E2%80%9Cpremature-optimization-is-the-root-of-all-evil%E2%80%9D&quot;&gt;9. “Premature optimization is the root of all evil” &lt;a class=&quot;direct-link&quot; href=&quot;#9.-%E2%80%9Cpremature-optimization-is-the-root-of-all-evil%E2%80%9D&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;DISAGREE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What is a &lt;em&gt;premature optimization&lt;/em&gt;?&lt;br&gt;
When does an &lt;em&gt;optimization&lt;/em&gt; cease to be &lt;em&gt;premature&lt;/em&gt;?&lt;br&gt;
What &lt;em&gt;evil&lt;/em&gt; are we talking about here?&lt;/p&gt;
&lt;p&gt;More seriously, &lt;a href=&quot;https://www.cs.sjsu.edu/~mak/archive/CS185C/KnuthStructuredProgrammingGoTo.pdf&quot;&gt;this quote&lt;/a&gt;, albeit super catchy &amp;amp; effective, is always dropped outside of its original context, which ironically, relates a &lt;strong&gt;very strong pro-optimization position&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;”The conventional wisdom shared by many of today&#39;s software engineers calls for ignoring efficiency in the small; but I believe this is simply an overreaction to the abuses they see being practiced by penny-wise-and-pound-foolish programmers.”&lt;/em&gt; &amp;gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/Donald_Knuth&quot;&gt;Donald Knuth&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I find it&#39;s often used as a lazy, vague, catch-all way to undermine someone&#39;s efforts or dismiss potential improvements, without much more justification - which, I&#39;m sure you&#39;ll agree, isn&#39;t very nice or respectful of said someone&#39;s work.&lt;br&gt;
In any case, I find it subjective, and would rather discuss the impact, the trade-offs or questions left to be answered, regarding the idea being challenged, in a more specific way.&lt;/p&gt;
&lt;p&gt;Moreover, looking back at the previous points, one could absolutely use this quote in a similarily disinguenous way to argue in favor of using these APIs over the potentially more complex, consequential, time consuming &amp;amp; risky alternatives, when any.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: This quote is also used in a more seasoned fashion, as an invitation to perform measurements, use profiling, to identify hot code paths in order to guide &amp;amp; validate performance improvement efforts, which in itself is perfectly recommendable.&lt;/p&gt;
&lt;h2 id=&quot;react-memo%2C-usememo-%26-usecallback-are-good%2C-actually&quot;&gt;React memo, useMemo &amp;amp; useCallback are good, actually &lt;a class=&quot;direct-link&quot; href=&quot;#react-memo%2C-usememo-%26-usecallback-are-good%2C-actually&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;React performance APIs have some weaknesses, yes, most of which inherent to their nature, filling in the gaps in React&#39;s rendering model &amp;amp; allowing teams to mitigate issues of their own making.&lt;br&gt;
However, incorrect uses of React performance APIs, in my experience, are mostly due to minor mistakes and inconsequential.&lt;br&gt;
On the other hand, strategic &amp;amp; proper use of these APIs can have an outstanding beneficial impact, on rendering performance of course, but also more than that: in expressing intent, surfacing key components, highlighting opportunities, enabling use cases that would otherwise require introducing a tremendous amount complexity or additional work, shipping now what would otherwise require days.&lt;br&gt;
All of which, in my book, makes &lt;strong&gt;React performance APIs exceptionally good, actually&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;demo%3A-let&#39;s-build-a-notes-app-highlighting-the-value-react-performance-apis&quot;&gt;Demo: Let&#39;s build a notes app highlighting the value React performance APIs &lt;a class=&quot;direct-link&quot; href=&quot;#demo%3A-let&#39;s-build-a-notes-app-highlighting-the-value-react-performance-apis&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;To be continued...:&lt;/em&gt; the idea would be to build, from scratch &amp;amp; step by step, a simple (fake) notes app, and during the process, highlighting the value of React performance APIs versus other possible alternatives, when any.&lt;/p&gt;
&lt;h2 id=&quot;i&#39;m-not-trying-to-convince-you&quot;&gt;I&#39;m not trying to convince you &lt;a class=&quot;direct-link&quot; href=&quot;#i&#39;m-not-trying-to-convince-you&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I consider that the uphill battle &lt;a href=&quot;https://tkdodo.eu/blog/the-uphill-battle-of-memoization&quot;&gt;&lt;s&gt;of memoization&lt;/s&gt;&lt;/a&gt; for the just &amp;amp; pragmatic recognition of the React performance APIs has long been lost.&lt;br&gt;
I&#39;m primarily writing this blog post for myself, and to serve as an educational reference and clarification of my views in case of future, alas inevitable, push-back &amp;amp; debates regarding the use of these APIs.&lt;br&gt;
I wish the React community generally wasn&#39;t so dogmatic, but regardless, for as long as I will even remotely be in contact with React code &amp;amp; React developers, I know I will continue to actively push for writing React code that&#39;s as efficient as reasonably possible, not just because I&#39;m a performance enthusiast and it&#39;s fun, but because it matters.&lt;/p&gt;
&lt;h2 id=&quot;to-be-continued...&quot;&gt;To be continued... &lt;a class=&quot;direct-link&quot; href=&quot;#to-be-continued...&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There&#39;s obviously much more to say on React Performance APIs and other gravitating topics.&lt;br&gt;
Further content (including the upcoming &lt;a href=&quot;#demo%3A-let&#39;s-build-a-notes-app-highlighting-the-value-react-performance-apis&quot;&gt;demo&lt;/a&gt;) may be added in the future, clarifications &amp;amp; corrections as well if needed.&lt;/p&gt;
&lt;h2 id=&quot;prior-art%3A-parisweb.app-(2018)&quot;&gt;Prior art: &lt;a href=&quot;https://parisweb.app/&quot;&gt;parisweb.app (2018)&lt;/a&gt; &lt;a class=&quot;direct-link&quot; href=&quot;#prior-art%3A-parisweb.app-(2018)&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Demo apps for the React/Redux performance workshop &lt;a href=&quot;https://www.paris-web.fr/2018/ateliers/petits-trucs-pour-rendre-vos-applications-react-plus-performantes.php&quot;&gt;“Petits trucs pour rendre vos applications React plus performantes”&lt;/a&gt; performed with &lt;a href=&quot;https://twitter.com/jwajsberg&quot;&gt;Julien Wajsberg&lt;/a&gt; at a meetup hosted by &lt;a href=&quot;https://www.gandi.net/&quot;&gt;Gandi&lt;/a&gt; and then at &lt;a href=&quot;https://www.paris-web.fr/&quot;&gt;Paris Web&lt;/a&gt; in 2018.&lt;br&gt;
The materials produced at this occasion (slides, code, examples) are mostly outdated, yet still somewhat relevant resources to understand and improve performance of React apps, with or without Redux, in 2023.&lt;/p&gt;
&lt;h2 id=&quot;thanks-for-reading!&quot;&gt;Thanks for reading! &lt;a class=&quot;direct-link&quot; href=&quot;#thanks-for-reading!&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you enjoyed this blog post, please feel free to share it and let me know on &lt;a href=&quot;https://twitter.com/tpillard&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://hachyderm.io/@tpillard&quot;&gt;Mastodon&lt;/a&gt;, don&#39;t hesitate to take a look at &lt;a href=&quot;https://timtech.blog/about/&quot;&gt;my about page&lt;/a&gt; as well.&lt;/p&gt;
&lt;h2 id=&quot;recommended-further-reading&quot;&gt;Recommended further reading &lt;a class=&quot;direct-link&quot; href=&quot;#recommended-further-reading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior&quot;&gt;A (Mostly) Complete Guide to React Rendering Behavior&lt;/a&gt;, by &lt;a href=&quot;https://twitter.com/acemarke&quot;&gt;Redux maintainer Mark &amp;quot;acemarke&amp;quot; Erikson&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
	</entry>
	
	<entry>
		<title>CSRF When You Least Expect It.</title>
		<link href="https://timtech.blog/posts/csrf-samesite-cookie-web-timing-attack/"/>
		<updated>2022-12-21T00:00:00+00:00</updated>
		<id>https://timtech.blog/posts/csrf-samesite-cookie-web-timing-attack/</id>
		<content type="html">&lt;p&gt;&lt;em&gt;Update 2022-12-21: I acknowledge this blog post isn’t as fun or interesting as I wanted it to be, it also contains a couple of minor errors.&lt;br&gt;
I still believe it covers an interesting topic, I’ll find a way to do it better.&lt;br&gt;
Thanks again to anyone who has read it and offered me their feedback.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update 2022-12-22: Previously stated that cookies were set with SameSite=Lax by default in modern browsers, which is incorrect.&lt;br&gt;
Updated with accurate browser compatibility info, links to the updated standard, MDN compatibility table, Firefox bug tracker.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;csrf&quot;&gt;CSRF &lt;a class=&quot;direct-link&quot; href=&quot;#csrf&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;img src=&quot;https://timtech.blog/img/seasurf-kaitlyn-jackson-LVbfbs0BPNY-unsplash.jpg&quot; alt=&quot;Black &amp; white photo of a surfer falling off their board&quot; width=&quot;480&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://unsplash.com/photos/LVbfbs0BPNY&quot;&gt;&lt;em&gt;Photo by Kaitlyn Jackson - Unsplash&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/csrf&quot;&gt;Cross-Site Request Forgery (CSRF)&lt;/a&gt; - a type of attack where the user&#39;s browser is tricked into &lt;strong&gt;performing unwanted actions&lt;/strong&gt; on a target website, on behalf of the user - are among the &lt;strong&gt;most common web application security risks&lt;/strong&gt;.&lt;br&gt;
As such, CSRF is usually well known among web developers, and most of today&#39;s websites are sufficiently protected against its most severe forms by implementing a set of &lt;a href=&quot;https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html&quot;&gt;best practices &amp;amp; defense mechanisms (OWASP)&lt;/a&gt; (ie: CSRF tokens, request origin checks, not using GET requests for state changing operations, ...).&lt;/p&gt;
&lt;p&gt;By the way, feel free to take a look at my &lt;a href=&quot;https://timtech.blog/posts/presentation-dashlane-web-extension-security-cross-origin-resource-sharing-CORS-OPTIONS-preflight-same-origin/&quot;&gt;Cross-Origin Resource Sharing For The Web (Extension)&lt;/a&gt; presentation for a refresher on the topic.&lt;/p&gt;
&lt;h3 id=&quot;samesite-cookies-%3F&quot;&gt;SameSite Cookies ? &lt;a class=&quot;direct-link&quot; href=&quot;#samesite-cookies-%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite&quot;&gt;SameSite Cookies&lt;/a&gt; allows you to declare if a cookie should be restricted to a first-party or same-site context. In other words, with either &lt;code&gt;SameSite=Lax&lt;/code&gt; or &lt;code&gt;SameSite=Strict&lt;/code&gt;, a cookie will &lt;em&gt;not be forwarded in cross-origin subrequests&lt;/em&gt;. Declaring session cookies as same-site are the &lt;a href=&quot;https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#samesite-cookie-attribute&quot;&gt;best defense-in-depth mitigation against CSRF&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;samesite%3Dlax-by-default-%3F&quot;&gt;SameSite=Lax by default ? &lt;a class=&quot;direct-link&quot; href=&quot;#samesite%3Dlax-by-default-%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Standard (&lt;a href=&quot;https://httpwg.org/http-extensions/draft-ietf-httpbis-rfc6265bis.html#name-the-samesite-attribute&quot;&gt;RFC 6265bis specification&lt;/a&gt;) recently changed so that &lt;code&gt;SameSite=Lax&lt;/code&gt; should be the default behavior if the &lt;code&gt;SameSite&lt;/code&gt; attribute is not specified in the &lt;code&gt;Set-Cookie&lt;/code&gt; HTTP response header.&lt;br&gt;
However, as of today (December 22nd 2022), this default behavior is either not yet implemented (Safari) or not yet activated by default (Firefox), for &lt;a href=&quot;https://browserslist.dev/?q=ZmlyZWZveCA%2BIDEsIHNhZmFyaSA%2BIDEsIGlPUyA%2BMQ%3D%3D&quot;&gt;22% of current browser coverage according to browserslist&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;samesite%3Dlax-default-behavior-browser-compatiblity%3A&quot;&gt;SameSite=Lax default behavior browser compatiblity: &lt;a class=&quot;direct-link&quot; href=&quot;#samesite%3Dlax-default-behavior-browser-compatiblity%3A&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chrome / Chrome Android&lt;/strong&gt;: 80&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Edge&lt;/strong&gt;: 86&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Opera&lt;/strong&gt;: 39&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Opera Android&lt;/strong&gt;: 60&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Samsung Internet&lt;/strong&gt;: 13&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebView Android&lt;/strong&gt;: 80&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Firefox&lt;/strong&gt;: 69 (pref &lt;code&gt;network.cookie.sameSite.laxByDefault&lt;/code&gt; - &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1617609&quot;&gt;bugzilla&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Firefox Android&lt;/strong&gt;: no&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Safari / Safari iOS&lt;/strong&gt;: no&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#browser_compatibility&quot;&gt;See SameSite Cookies Browser Compatibility on MDN&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;samesite%3Dnone&quot;&gt;SameSite=None &lt;a class=&quot;direct-link&quot; href=&quot;#samesite%3Dnone&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;However, there are &lt;strong&gt;still many websites&lt;/strong&gt; out there which rely on &lt;code&gt;SameSite=None&lt;/code&gt; as they:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;don&#39;t specify the &lt;code&gt;SameSite&lt;/code&gt; attribute for their cookies, their Firefox &amp;amp; Safari users thus getting the &lt;code&gt;SameSite=None&lt;/code&gt; behavior&lt;/li&gt;
&lt;li&gt;already existed &lt;em&gt;before the introduction of SameSite cookies&lt;/em&gt; (from around 2016 to 2020 depending on the browser and stage of implementation), and thus already had &lt;em&gt;prior controls in place against CSRF&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;still need to include cookies in cross-site requests, probably for some &lt;em&gt;obscure tracking purposes&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://duckduckgo.com/?q=site%3Astackoverflow.com+%22SameSite%3DNone%22&quot;&gt;aren&#39;t necessarily sure what they&#39;re doing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But since these sites are using other anti-CSRF mechanisms &amp;amp; SameSite cookies are “defense in depth”, this should be fine, right? &lt;strong&gt;RIGHT?&lt;/strong&gt;&lt;br&gt;
Well, mostly, I mean, kinda ... it depends ... &lt;strong&gt;ok not really.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;introducing-timing-attacks&quot;&gt;Introducing Timing Attacks &lt;a class=&quot;direct-link&quot; href=&quot;#introducing-timing-attacks&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A timing attack is a &lt;strong&gt;side-channel attack&lt;/strong&gt; in which an attacker is able to gather information by &lt;strong&gt;measuring the time various operations take to run&lt;/strong&gt;.&lt;br&gt;
It is usually referred to in the context of &lt;em&gt;cryptographic algorithms&lt;/em&gt;, or in the case of &lt;a href=&quot;https://en.wikipedia.org/wiki/Transient_execution_CPU_vulnerability&quot;&gt;transient execution CPU vulnerabilities&lt;/a&gt; such as the famous &lt;a href=&quot;https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)&quot;&gt;Spectre&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://en.wikipedia.org/wiki/Meltdown_(security_vulnerability)&quot;&gt;Meltdown&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;timing-attacks-...-on-the-web-%3F&quot;&gt;Timing Attacks ... on the Web ? &lt;a class=&quot;direct-link&quot; href=&quot;#timing-attacks-...-on-the-web-%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;However, per Wikipedia, “timing attacks can be applied to any algorithm that has data-dependent timing variation” and, what more than today&#39;s websites that, gated behind authentication &amp;amp; user accounts, querying a myriad of unequally optimized microservices in order to display user-specific content, are subject to ”data-dependent timing variation” ?&lt;br&gt;
It is fair to assume the server handling requests to pages for user dashboards or social media timelines for example, behave &lt;em&gt;slightly differently&lt;/em&gt; whether or not the user is &lt;em&gt;logged-in or not&lt;/em&gt;.&lt;br&gt;
Indeed, in a lot of cases, those requests will take &lt;strong&gt;significantly longer&lt;/strong&gt; to be answered compared to the login page that is served (or redirected to) in its place.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: this assumption may not be true for some websites, nowadays even personalized content can be heavily cached, and public content may not be faster to retrieve either.&lt;br&gt;
However, as mentioned earlier, things are rarely equally optimized, which means that even though the main personalized content of a given websites may be very fast to retrieve, it may not be not the case for more niche content, located at another URL.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Ok that&#39;s cool and all, but what does it have to do with CSRF &amp;amp; SameSite Cookies?&lt;/p&gt;
&lt;h3 id=&quot;csrf-based-web-timing-attacks&quot;&gt;CSRF Based Web Timing Attacks &lt;a class=&quot;direct-link&quot; href=&quot;#csrf-based-web-timing-attacks&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Given a website that use &lt;code&gt;SameSite=None&lt;/code&gt; for their session cookies, and, even with some &lt;em&gt;safeguards&lt;/em&gt; against most common &amp;amp; severe forms of CSRF, we can still perform attacks that fall into the CSRF category, in fact, in an actually much simpler way than with usual forged cross-site requests.&lt;br&gt;
The twist resides in actually sending out &lt;strong&gt;two simple GET requests, with &amp;amp; without credentials&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;one cross-origin request &lt;em&gt;omitting credentials (cookies)&lt;/em&gt;, which will yield a &lt;em&gt;public version of the page&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;one cross-origin request &lt;em&gt;including credentials (cookies)&lt;/em&gt;, which will yield the &lt;em&gt;private version of the page&lt;/em&gt; if the victim is logged-in&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can do this easily with JavaScript using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/fetch&quot;&gt;Fetch API&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://target.example.com/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  credentials&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;omit&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note: for optimal results on a case by case basis, one may further tune the parameters of the requests &amp;amp; the behavior of the browser according to the &lt;a href=&quot;https://fetch.spec.whatwg.org/&quot;&gt;Fetch Standard&lt;/a&gt;, by using the &lt;code&gt;mode&lt;/code&gt; &amp;amp; &lt;code&gt;redirect&lt;/code&gt; options.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now these requests are made from a given origin, let&#39;s say &lt;code&gt;https://evil.example.com&lt;/code&gt;, to another origin, say &lt;code&gt;https://target.example.com&lt;/code&gt;.&lt;br&gt;
Of course, in real life those would be totally different domains, but in any case, they&#39;re different origins, and, for this example to be correct, we&#39;re assuming that session cookies weren&#39;t set with the &lt;code&gt;Domain&lt;/code&gt; directive.&lt;/p&gt;
&lt;p&gt;Due to &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy&quot;&gt;Same-Origin Policy&lt;/a&gt; (and the target origin presumably not allowing our evil origin with the &lt;code&gt;Access-Control-Allow-Origin: https://evil.example.com&lt;/code&gt; response header), the responses from these requests are &lt;strong&gt;opaque&lt;/strong&gt; and &lt;strong&gt;cannot be read&lt;/strong&gt;, so we can&#39;t poke around in the response HTML for the actual content.&lt;br&gt;
But we&#39;re fine with that, as mentioned earlier, we&#39;re interested in the timing of things, and that, we do have access to!&lt;br&gt;
All we have to do is to measure the time it took between the firing of the request, and the subsequent settlement (rejection) of the Fetch promise.&lt;br&gt;
Again, this is only possible because &lt;code&gt;https://target.example.com&lt;/code&gt; is using &lt;code&gt;SameSite=None&lt;/code&gt; session cookies.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://target.example.com/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  credentials&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;omit&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token comment&quot;&gt;// swallow the likely NetworkError exception occuring from the CORS error.&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the following code, we are able to put together an attacker webpage, get an hypothetical victim to visit it, and begin poking around to find out if, for a given URL, fetches take significantly longer to respond with credentials (cookies) included, or not.&lt;br&gt;
If they do, chances are you are &lt;strong&gt;able to detect whether or not the user is logged-in to this particular website&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;However, in order to have more confidence in the results, we should update our exploit code to be aware of what constitutes &lt;em&gt;&amp;quot;significantly longer&amp;quot;&lt;/em&gt;, for instance, we could draw the line at a 40% tolerance.&lt;br&gt;
We also might want our code to repeat the experiment a few times and ensure that the results are the same 80% of the time, so we&#39;d be able to tell the results are &lt;em&gt;consistent&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/ziir/98b79638b4cb889c1b718e56eab0f68a&quot;&gt;View Gist with complete example code of the malicious page&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;how-could-this-be-used-%3F&quot;&gt;How could this be used ? &lt;a class=&quot;direct-link&quot; href=&quot;#how-could-this-be-used-%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Such Web Timing Attacks could be used by bad actors in order to further &lt;strong&gt;identify potential targets&lt;/strong&gt;, for example as the ~first of a multi-stage attack, starting from a spam campaign linking to a malicious webpage controlled by the attacker and containing the exploit code, allowing them to identify whether or not &lt;em&gt;victims are users of specific sites or services&lt;/em&gt;, before engaging in a more targeted phishing campaign.&lt;br&gt;
Depending on the website or service being targeted and after careful analysis by the attackers, one may even be able to gather more precise information about the victim than just their authentication status: potentially their &lt;em&gt;customer profile&lt;/em&gt; (ie: a specific page of a given website may take a very long or telling time to load, when in the context of a large business).&lt;/p&gt;
&lt;h3 id=&quot;how-to-prevent-such-web-timing-attacks-%3F&quot;&gt;How to prevent such web timing attacks ? &lt;a class=&quot;direct-link&quot; href=&quot;#how-to-prevent-such-web-timing-attacks-%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Do not use &lt;code&gt;SameSite=None&lt;/code&gt;, use either &lt;code&gt;SameSite=Strict&lt;/code&gt; or &lt;code&gt;SameSite=Lax&lt;/code&gt;: this way, cookies will not be forwarded in cross-origin subrequests.&lt;/li&gt;
&lt;li&gt;Use a modern, up-to-date web browser, in fact, &lt;a href=&quot;https://www.mozilla.org/en-US/firefox/browsers/&quot;&gt;use Firefox&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;bad-performance-is-bad-security&quot;&gt;Bad Performance is Bad Security &lt;a class=&quot;direct-link&quot; href=&quot;#bad-performance-is-bad-security&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One slightly disingenuous way of looking at this is to blame the feasability of this attack on the lack of performance focus: if &lt;strong&gt;everything&lt;/strong&gt; is as fast as it can be, then a third party cannot interpolate private information based on response times.&lt;br&gt;
Alternatively, one other way to look at this is to aim for making all requests roughly respond in the same time, by artificially slowing them down, but that would be silly, &lt;strong&gt;please don&#39;t do that&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;don&#39;t-try-this-at-home&quot;&gt;Don&#39;t try this at home &lt;a class=&quot;direct-link&quot; href=&quot;#don&#39;t-try-this-at-home&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Or rather, &lt;strong&gt;please do try this at home&lt;/strong&gt;, but don&#39;t use this for &lt;em&gt;nefarious purposes&lt;/em&gt;, I wrote this article for fun &lt;u&gt;and profit&lt;/u&gt; and somewhat educational purposes.&lt;/p&gt;
&lt;h3 id=&quot;share-the-love&quot;&gt;Share the love &lt;a class=&quot;direct-link&quot; href=&quot;#share-the-love&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you enjoyed this article, please feel free to share it and let me know on &lt;a href=&quot;https://twitter.com/tpillard&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://hachyderm.io/@tpillard&quot;&gt;Mastodon&lt;/a&gt;, don&#39;t hesitate to take a look at &lt;a href=&quot;https://timtech.blog/about/&quot;&gt;my about page&lt;/a&gt; as well.&lt;br&gt;
Did I mention I&#39;m looking for a job?&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Cross-Origin Resource Sharing For The Web (Extension).</title>
		<link href="https://timtech.blog/posts/presentation-dashlane-web-extension-security-cross-origin-resource-sharing-CORS-OPTIONS-preflight-same-origin/"/>
		<updated>2021-03-16T00:00:00+00:00</updated>
		<id>https://timtech.blog/posts/presentation-dashlane-web-extension-security-cross-origin-resource-sharing-CORS-OPTIONS-preflight-same-origin/</id>
		<content type="html">&lt;p&gt;As I&#39;m getting close to my fifth month at &lt;a href=&quot;https://www.dashlane.com/&quot;&gt;Dashlane&lt;/a&gt;, I have given my second presentations to engineers within the Web Product Team.&lt;/p&gt;
&lt;p&gt;The presentation aims to be a high-level introduction to &lt;strong&gt;Cross-Origin Resource Sharing&lt;/strong&gt;.&lt;br&gt;
It covers the key concepts needed to approach CORS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Origin&lt;/li&gt;
&lt;li&gt;Same-Origin Policy&lt;/li&gt;
&lt;li&gt;Cross-Site Request Forgery (CSRF)&lt;/li&gt;
&lt;li&gt;OPTIONS preflight requests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It also tells &lt;a href=&quot;https://twitter.com/tpillard/status/1349669957764861952&quot;&gt;the tale of a CORS twist in the context of a Chrome Web Extension&lt;/a&gt;.&lt;br&gt;
Finally, the presentation mentions &lt;a href=&quot;https://w3c.github.io/webappsec-post-spectre-webdev/&quot;&gt;the quickly evolving web security landscape in a post-spectre world&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This presentation is also kind of meant as a not so subtle invitation to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;double-checking your cross-origin setup.&lt;/li&gt;
&lt;li&gt;being wary of relying on defaults implemented by browsers.&lt;/li&gt;
&lt;li&gt;not blindly trusting the specifications.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://timtech.blog/public/timtechblog-dashlane-presentation-cross-origin-resource-sharing-march-2021.pdf&quot;&gt;Open “Cross-Origin Resource Sharing For The Web (Extension) (3.99MB pdf)”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This presentation was given over video conference using screen sharing, in about 30 minutes excluding questions.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Forms handling with React: Giving Up Control.</title>
		<link href="https://timtech.blog/posts/presentation-dashlane-react-form-handling-giving-up-control-example-controlled-input/"/>
		<updated>2020-12-19T00:00:00+00:00</updated>
		<id>https://timtech.blog/posts/presentation-dashlane-react-form-handling-giving-up-control-example-controlled-input/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://twitter.com/tpillard/status/1324383879013216256&quot;&gt;As announced on Twitter&lt;/a&gt;, I recently joined &lt;a href=&quot;https://www.dashlane.com/&quot;&gt;Dashlane&lt;/a&gt;, and gave my first presentation to engineers within the Web Product team.&lt;/p&gt;
&lt;p&gt;The presentation aims to be a high-level introduction to forms handling with React.&lt;br&gt;
It covers the key differences between a traditional form handling approach with JavaScript, and both the &lt;strong&gt;controlled input&lt;/strong&gt; (or &lt;em&gt;controlled component&lt;/em&gt;) and &lt;strong&gt;uncontrolled input&lt;/strong&gt; approaches.&lt;br&gt;
It also gives food for thought on how to consider going one way or the other for the implementation inside an existing React project for the Web.&lt;/p&gt;
&lt;p&gt;This presentation is also kind of meant as a not so subtle invitation to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;further considering &lt;em&gt;uncontrolled inputs&lt;/em&gt; in form implementations using React&lt;/li&gt;
&lt;li&gt;keeping an open mind and remaining critical of &lt;em&gt;“The React Philosophy (tm)”&lt;/em&gt; and &lt;em&gt;thought leadering&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&#39;re further interested, in particular by the performance implications of controlled inputs and React performance in general, I invite you to take a look at a previous presentation (in french), and other materials made at the occasion of &lt;a href=&quot;https://parisweb.app/&quot;&gt;Paris Web workshop in 2018: “Petits trucs pour rendre vos applications React plus performantes”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://timtech.blog/public/timtechblog-dashlane-react-form-handling-intro-giving-up-control-december-2020.pdf&quot;&gt;Open “Forms handling with React: Giving Up Control (1.41MB pdf)”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This presentation was given over video conference using screen sharing, in about 20 minutes excluding questions.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Read “Reflecting on our JavaScript footprint” on Gandi&#39;s blog.</title>
		<link href="https://timtech.blog/posts/read-reflecting-javascript-footprint-at-gandi/"/>
		<updated>2020-08-12T00:00:00+00:00</updated>
		<id>https://timtech.blog/posts/read-reflecting-javascript-footprint-at-gandi/</id>
		<content type="html">&lt;p&gt;July 31th 2020 was my last day as &lt;a href=&quot;https://timtech.blog/about/&quot;&gt;Lead Front-End Engineer&lt;/a&gt; at &lt;a href=&quot;https://www.gandi.net/&quot;&gt;Gandi&lt;/a&gt;.&lt;br&gt;
&lt;a href=&quot;https://twitter.com/tpillard/status/1289276041261920261&quot;&gt;As announced on Twitter&lt;/a&gt;, I have spent my last few hours there writing an article to be published on &lt;a href=&quot;https://news.gandi.net/&quot;&gt;Gandi&#39;s blog&lt;/a&gt;: &lt;a href=&quot;https://news.gandi.net/en/2020/07/reflecting-on-our-javascript-footprint/&quot;&gt;Reflecting on our JavaScript footprint&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After quickly describing the changes occuring on the Web, this article introduces the concept of &lt;strong&gt;JavaScript footprint&lt;/strong&gt; by examining the architecture of two websites I have been working on at Gandi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gandi.net/&quot;&gt;https://www.gandi.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://shop.gandi.net/&quot;&gt;https://shop.gandi.net&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article contains insights on how Gandi is organized, develops websites, the difficulties that are met, as well as some leads and solutions towards solving these.&lt;/p&gt;
&lt;p&gt;There&#39;s a lot of interesting topics, contents that, for the sake of brievety, and in order to meet a very tight deadline, did not make it into the article that I intend to develop on this blog, so stay tuned. :)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://news.gandi.net/en/2020/07/reflecting-on-our-javascript-footprint/&quot;&gt;Read Reflecting on our JavaScript footprint on Gandi&#39;s blog&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Limiting Asynchronous Operations Concurrency In JavaScript.</title>
		<link href="https://timtech.blog/posts/limiting-async-operations-promise-concurrency-javascript/"/>
		<updated>2020-08-07T00:00:00+00:00</updated>
		<id>https://timtech.blog/posts/limiting-async-operations-promise-concurrency-javascript/</id>
		<content type="html">&lt;p&gt;Today&#39;s post is about a little trick I have learned about 2years ago, and that I have since used numerous times in short Node.js scripts I had to write.&lt;br&gt;
It really isn&#39;t much, but I guess it may be helpful to others, and probably is an alright first JavaScript post on this blog.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Say one has a list of things, and for every of these things, one needs to perform an asynchronous operation that returns a Promise, and be notified when all operations have been performed.&lt;/em&gt; &amp;gt; &lt;em&gt;How does one limit the number of asynchronous operations being performed conccurently? Without 3rd party dependencies and just a few lines of code?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Are you seeing the problem yet? Let&#39;s build some context:&lt;/p&gt;
&lt;h3 id=&quot;we-have-a-list-of-99-things%2C-say-resource-identifiers&quot;&gt;We have a list of 99 things, say resource identifiers &lt;a class=&quot;direct-link&quot; href=&quot;#we-have-a-list-of-99-things%2C-say-resource-identifiers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ids &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;for-each-of-these-things%2C-we-need-to-perform-an-asynchronous-operation&quot;&gt;For each of these things, we need to perform an asynchronous operation &lt;a class=&quot;direct-link&quot; href=&quot;#for-each-of-these-things%2C-we-need-to-perform-an-asynchronous-operation&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, let&#39;s define the function that will perform said asynchronous operation:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// We can pretend this performs an HTTP request&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// an API call, or a database query.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;performAsyncOperation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Performed operation for resource &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we know that we need to call this function of every single thing out of our list of 99 things, every resource id we have in &lt;code&gt;ids&lt;/code&gt;.&lt;br&gt;
Our first approach, would be to naively use &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map&quot;&gt;Array.prototype.map&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/all&quot;&gt;Promise.all&lt;/a&gt; and call it a day. But let&#39;s have a closer look to this innocent line of code and its implications:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;performAsyncOperation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;All operations performed, moving on to something else now.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note: we might arguably use &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled&quot;&gt;Promise.allSettled&lt;/a&gt; in a real world scenario, but let&#39;s assume our asynchronous operations cannot fail.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Which we would give us the following complete script:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;performAsyncOperation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Performed operation for resource &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;      &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ids &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;performAsyncOperation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;All operations performed in &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;br&gt;      end &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start&lt;br&gt;    &lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;ms, moving on to something else now.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, let&#39;s run it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ node async-operations-promise-all.js
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[tim@praxis ~]$ node limit-async.js
Performed operation for resource 1.
Performed operation for resource 2.
Performed operation for resource 3.
...
Performed operation for resource 97.
Performed operation for resource 98.
Performed operation for resource 99.
All operations performed in 338ms, moving on to something else now.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see, ~all the asynchronous operations were performed &lt;strong&gt;concurrently&lt;/strong&gt;, and sometimes, that&#39;s perfectly fine and exactly what we want.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: &lt;code&gt;Promise.all&lt;/code&gt; only waits for all the &lt;strong&gt;Promises&lt;/strong&gt; to be resolved. The actual asynchronous operation is triggered by the function call from &lt;code&gt;Array.prototype.map&lt;/code&gt;, creating a new &lt;strong&gt;Promise&lt;/strong&gt; on each call.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-problem-of-performing-operations-concurrently&quot;&gt;The problem of performing operations concurrently &lt;a class=&quot;direct-link&quot; href=&quot;#the-problem-of-performing-operations-concurrently&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now, let&#39;s assume that our &lt;code&gt;performAsyncOperation&lt;/code&gt; really performs an HTTP request, an API Call, a database query, or really anything else that would either suffer or punish us for the load we push on to it. It might be a rate-limited API, or a fragile host.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: in the actual case of an HTTP request, or database query, the Web/Node.js/etc... API being used will already probably limit concurrency, of which value may or may not configurable, but let&#39;s assume that we cannot or do not want to change such settings.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In such cases, we simply cannot allow our script to perform all these operations &lt;strong&gt;concurrently&lt;/strong&gt;, as it risks getting our API key revoked, our IP blocked, or the target host/database responding unreliably, etc... Thus we will be searching for a way to limit &lt;strong&gt;JavaScript concurrency&lt;/strong&gt; to avoid such scenario.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: depending on the actual work performed by the asynchronous operation, performing many of these concurrently may also make the process running it consuming significant amount of CPU and/or memory resources on the machine it runs.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-solution%3A-performing-asynchronous-operations-sequentially&quot;&gt;A solution: performing asynchronous operations sequentially &lt;a class=&quot;direct-link&quot; href=&quot;#a-solution%3A-performing-asynchronous-operations-sequentially&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first solution that may come to mind, would be to perform each of these operations &lt;strong&gt;sequentially&lt;/strong&gt;, on task at a time:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ids &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;performAsyncOperation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/del&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; id &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; ids&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;   &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;performAsyncOperation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;All operations performed in &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;end &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;ms, moving on to something else now.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which, if we run this script, gives the following output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[tim@praxis ~]$ node limit-async.js
Performed operation for resource 1.
Performed operation for resource 2.
Performed operation for resource 3.
...
Performed operation for resource 97.
Performed operation for resource 98.
Performed operation for resource 99.
All operations performed in 29825ms, moving on to something else now.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we&#39;d expect, every operation awaits for the previous one to be completed, and, in a way, we found a succesful solution to our problem.&lt;br&gt;
However, one would probably argue this being far from optimal, and that the system against which we run these asynchronous operations can safely withstand up to 3 concurrent operations, thus, our script could theoretically be ~3 times faster.&lt;/p&gt;
&lt;h3 id=&quot;the-solution%3A-limiting-concurrency-using-workers&quot;&gt;The solution: limiting concurrency using workers &lt;a class=&quot;direct-link&quot; href=&quot;#the-solution%3A-limiting-concurrency-using-workers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now, let&#39;s take a look at how we can update our script to perform at most 3 operations concurrently.&lt;br&gt;
For that, let&#39;s introduce a &lt;code&gt;worker&lt;/code&gt; function, to which we will delegate the job of performing one asynchronous operation at a time.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;worker&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;next_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;next_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;performAsyncOperation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note: such a &lt;code&gt;worker&lt;/code&gt; function can be implemented in various ways, this implementation is just an example of what I&#39;ve used in the past.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;However big the number of asynchronous operations we wish to perform, we will ever need at most, 3 concurrent &lt;code&gt;workers&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CONCURRENT_WORKERS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will then want to give a way to our &lt;code&gt;workers&lt;/code&gt; to retrieve the next resource identifier, or thing, to perform the asynchronous operation from.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; workers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CONCURRENT_WORKERS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; w &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;  workers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let us update our script:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;performAsyncOperation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Performed operation for resource &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;worker&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;next_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;next_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;performAsyncOperation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CONCURRENT_WORKERS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ids &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; workers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CONCURRENT_WORKERS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; w &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;    workers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;workers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;All operations performed in &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;end &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;ms, moving on to something else now.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And run it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[tim@praxis ~]$ node limit-async.js
Performed operation for resource 1.
Performed operation for resource 2.
Performed operation for resource 3.
...
Performed operation for resource 97.
Performed operation for resource 98.
Performed operation for resource 99.
All operations performed in 9948ms, moving on to something else now.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;bonus-solution%3A-batching-concurrent-operations&quot;&gt;Bonus solution: batching concurrent operations &lt;a class=&quot;direct-link&quot; href=&quot;#bonus-solution%3A-batching-concurrent-operations&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&#39;s one more way to look at the problem, and reach another solution: splitting the asynchronous operations to be performed in &lt;strong&gt;batches&lt;/strong&gt;.&lt;br&gt;
In our case, if we have 99 operations to perform, we can split these into 33 batches of 3 operations.&lt;br&gt;
With batching, every operation within one batch will be performed conccurently, and the next batch will only be started once the previous one is finished.&lt;br&gt;
How does one implement concurrent tasks batching with JavaScript?&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ids &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;performAsyncOperation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/del&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;   &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;splice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;performAsyncOperation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;   console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Performed async operactions batch number&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;   i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/ins&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;All operations performed in &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;end &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;ms, moving on to something else now.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which gives us the following output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[tim@praxis ~]$ node limit-async.js
Performed operation for resource 1.
Performed operation for resource 2.
Performed operation for resource 3.
Performed async operactions batch number 1
...
Performed operation for resource 97.
Performed operation for resource 98.
Performed operation for resource 99.
Performed async operactions batch number 33
All operations performed in 9981ms, moving on to something else now.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Asynchronous JavaScript can be tricky, and though one may argue the language lacks high-level APIs to deal more efficiently with some of these tricky cases like the one we&#39;ve just covered, it&#39;s always worth taking our chance at solving the problems leveraging the features that we&#39;re provided by the language.&lt;/p&gt;
&lt;p&gt;In this post we&#39;ve built and lived through a common scenario of managing asynchronous operations concurrency in JavaScript, along with a common pitfall associated with a naive approach, as well as an intermediary solution that is also very useful on some other cases, and finally the optimal solution for dealing with this problem, all without using third party modules. I hope this may be useful to some of you, and that I did not take too many shortcuts in the process.&lt;/p&gt;
&lt;p&gt;If you liked this post, feel free to encourage me by saying so on &lt;a href=&quot;https://twitter.com/tpillard&quot;&gt;my Twitter&lt;/a&gt; and/or by liking/retweeting the associated tweet or sharing the article around you.&lt;br&gt;
Finally, feel free to share your feedback if you have ideas or know how I can improve this post or this blog, thank you :)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: special thanks to &lt;a href=&quot;https://twitter.com/baloose&quot;&gt;baloo&lt;/a&gt; for teaching me this trick while I was hacking together a script purposed to pre-fill HTTP cache server entries for a given website from its sitemap file.&lt;/em&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Setting up this blog (quickly) with Eleventy.</title>
		<link href="https://timtech.blog/posts/setting-up-this-blog-quickly-with-eleventy/"/>
		<updated>2020-08-06T00:00:00+00:00</updated>
		<id>https://timtech.blog/posts/setting-up-this-blog-quickly-with-eleventy/</id>
		<content type="html">&lt;h3 id=&quot;hey%2C-welcome!&quot;&gt;Hey, welcome! &lt;a class=&quot;direct-link&quot; href=&quot;#hey%2C-welcome!&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&#39;ve been wanting to have a tech blog of my own I could write on for a while now...&lt;br&gt;
And so I have tried to set one up a few times over the years, always with the same goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;not rely on a third party platform such as Medium and the like&lt;/li&gt;
&lt;li&gt;not code it all myself, because who&#39;s got time for that&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All my previous attempts failed, roughly at the same stage, whether it was full-features CMSs such as Wordpress or Ghost, or static site generators such as Gatsby. Every time, something felt off: it would require too much work for me to get what I wanted, or, more accurately: it would require too much work for me &lt;strong&gt;to get rid of all the stuff that I did not want&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here are a few examples of things I do not want:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;node_modules&lt;/code&gt; bloat&lt;/li&gt;
&lt;li&gt;JavaScript / markup bloat&lt;/li&gt;
&lt;li&gt;client-side rendering&lt;/li&gt;
&lt;li&gt;complicated webserver runtime, database engine&lt;/li&gt;
&lt;li&gt;overly complex APIs &amp;amp; tooling&lt;/li&gt;
&lt;li&gt;etc...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Paradoxically (or, is it?), it is now that I have much more time on my hands that I have found the way forward.&lt;/p&gt;
&lt;h3 id=&quot;eleventy-(11ty)%2C-a-simpler-static-site-generator&quot;&gt;Eleventy (11ty), a simpler static site generator &lt;a class=&quot;direct-link&quot; href=&quot;#eleventy-(11ty)%2C-a-simpler-static-site-generator&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I have been hearing about &lt;a href=&quot;https://11ty.dev/&quot;&gt;Eleventy (11ty), a simpler static site generator&lt;/a&gt; for quite some time now and decided to give it a spin.&lt;br&gt;
Immediately upon opening Eleventy Documentation, I stumbled upon the &lt;a href=&quot;https://www.11ty.dev/docs/starter/&quot;&gt;Starter Projects&lt;/a&gt;, and more specifically, the &lt;a href=&quot;https://github.com/11ty/eleventy-base-blog&quot;&gt;eleventy-base-blog starter project&lt;/a&gt;. Skipping further reading of the documentation, let&#39;s take a look at the steps I followed that led me to having this blog ready for ~production within a few hours.&lt;/p&gt;
&lt;h3 id=&quot;this-is-a-not-a-tutorial&quot;&gt;This is a not a tutorial &lt;a class=&quot;direct-link&quot; href=&quot;#this-is-a-not-a-tutorial&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gandi.net/domain&quot;&gt;Register a domain name&lt;/a&gt; first, as any good procrastinator with a side-project idea would&lt;/li&gt;
&lt;li&gt;Clone &lt;a href=&quot;https://github.com/11ty/eleventy-base-blog&quot;&gt;eleventy-base-blog starter project&lt;/a&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;$ cd Repositories
$ git clone git@github.com:11ty/eleventy-base-blog.git timtech.blog
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Start the development server:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;$ cd timtech.blog
$ npm install
$ npm start
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Fiddle with the Nunjucks templates, the CSS file&lt;/li&gt;
&lt;li&gt;Add a webfont: &lt;a href=&quot;https://mozilla.github.io/Fira/&quot;&gt;Fira Sans&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;downloaded as &lt;code&gt;.tff&lt;/code&gt; from &lt;a href=&quot;https://fonts.google.com/specimen/Fira+Sans&quot;&gt;Google Fonts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;exported to &lt;code&gt;.woff2&lt;/code&gt; (+ subsetting, etc...) using &lt;a href=&quot;https://www.fontsquirrel.com/tools/webfont-generator&quot;&gt;Font Squirrel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Fiddle some more &lt;code&gt;.eleventy.js&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt; files and other stuff&lt;/li&gt;
&lt;li&gt;Write this post in Markdown&lt;/li&gt;
&lt;li&gt;Create a GitHub repository&lt;/li&gt;
&lt;li&gt;Set git remote, commit, push:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;$ rm -rf .git
$ git init
$ git remote add git@github.com:ziir/timtech.blog.git
$ git add .
$ git commit -m &amp;quot;initial commit&amp;quot;
$ git push origin master
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;And... voila! (conveniently leaving out the deploy &amp;amp; hosting part)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://timtech.blog/img/timtech-blog-lighthouse-100-eleventy.png&quot; alt=&quot;timtech.blog scoring 100s on Lighthouse&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;now%2C-is-this-blog-perfect%3F&quot;&gt;Now, is this blog perfect? &lt;a class=&quot;direct-link&quot; href=&quot;#now%2C-is-this-blog-perfect%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Absolutely not, it&#39;s just the bare minimum for me to push my content out there.&lt;/p&gt;
&lt;h3 id=&quot;what-about-eleventy%2C-is-it-good%3F&quot;&gt;What about Eleventy, is it good? &lt;a class=&quot;direct-link&quot; href=&quot;#what-about-eleventy%2C-is-it-good%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The fact that I was able to hack together a decent blog out of it without being familiar with it or reading any documentation puts it in a good position I believe.&lt;br&gt;
There&#39;s one thing in particular that I appreciate of &lt;code&gt;Eleventy&lt;/code&gt;: I mentionned earlier that the other options I had tried previously didn&#39;t satisfy me and, in some way, would be forcing too much work on me to remove all of the stuff that I did not want, and so far, &lt;code&gt;Eleventy&lt;/code&gt; hasn&#39;t given me any of those.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://timtech.blog/img/timtech-blog-post-requests.png&quot; alt=&quot;timtech.blog post requests as seen in Firefox Devtools&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-next%3F&quot;&gt;What next? &lt;a class=&quot;direct-link&quot; href=&quot;#what-next%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now begins the journey of this blog, built with &lt;code&gt;Eleventy&lt;/code&gt;. There&#39;s a bunch of things that this blog is currently missing and that I am fairly confident I will be able to implement with ease using &lt;code&gt;Eleventy&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a search feature, even as a static site&lt;/li&gt;
&lt;li&gt;pagination&lt;/li&gt;
&lt;li&gt;some sort of a comments system&lt;/li&gt;
&lt;li&gt;an original webdesign&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind CSS&lt;/a&gt;, because &lt;em&gt;I love utility-first&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;offline-first PWA&lt;/li&gt;
&lt;li&gt;more stuff I&#39;ll make up along the way&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;what-if-eleventy-is-not-up-to-the-task%3F&quot;&gt;What if Eleventy is not up to the task? &lt;a class=&quot;direct-link&quot; href=&quot;#what-if-eleventy-is-not-up-to-the-task%3F&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If, for some reason, I am not satisfied by &lt;code&gt;Eleventy&lt;/code&gt; for the purposes of this blog, moving away from it to some other tool should be pretty easy.&lt;br&gt;
Let&#39;s take a look of the things I would want to keep in such a scenario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/posts/:slug&lt;/code&gt;, &lt;code&gt;/tags/:tag&lt;/code&gt;, &lt;code&gt;/about&lt;/code&gt;, etc... URLs &amp;amp; associated content&lt;/li&gt;
&lt;li&gt;JSON / Atom feeds&lt;/li&gt;
&lt;li&gt;a sitemap&lt;/li&gt;
&lt;li&gt;and... that&#39;s it!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;wrapping-things-up&quot;&gt;Wrapping things up &lt;a class=&quot;direct-link&quot; href=&quot;#wrapping-things-up&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While it&#39;s usually best to weigh the pros and cons of available options before committing to either of them, sometimes it really is fine to just try it, move forward and adapt along the way, even if the first results are far from perfection.&lt;/p&gt;
</content>
	</entry>
</feed>
