<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Viktor Lázár</title>
    <description>The latest articles on Forem by Viktor Lázár (@lazarv).</description>
    <link>https://forem.com/lazarv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1115191%2Fd5ca33e8-94a4-4cdf-9452-400c95556d9c.jpeg</url>
      <title>Forem: Viktor Lázár</title>
      <link>https://forem.com/lazarv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lazarv"/>
    <language>en</language>
    <item>
      <title>The Illusion of Language: What Directives Really Are</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Sun, 09 Nov 2025 11:35:27 +0000</pubDate>
      <link>https://forem.com/lazarv/the-illusion-of-language-what-directives-really-are-445</link>
      <guid>https://forem.com/lazarv/the-illusion-of-language-what-directives-really-are-445</guid>
      <description>&lt;h2&gt;
  
  
  Preface &amp;amp; Introduction — Why This Post Exists
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This post is not a rebuttal.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s a reflection inspired by the great &lt;strong&gt;“Directives and the Platform Boundary”&lt;/strong&gt; article by Tanner Linsley. I genuinely enjoyed the piece and agree with many of its points — especially around ownership, provenance, and the value of explicit APIs.&lt;br&gt;
What I wanted to add is a slightly different lens: one that comes from building directive-driven tooling and from having lived through a very similar chapter in programming history, long before JavaScript had &lt;code&gt;'use client'&lt;/code&gt; or &lt;code&gt;'use server'&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Over the past year, I’ve watched countless developers treat directives in JavaScript as if they were &lt;strong&gt;actual language features&lt;/strong&gt; — something built into the JavaScript spec or the runtime environment. And to be fair, at a glance, it &lt;em&gt;does&lt;/em&gt; look that way. A string at the top of a file that magically changes how the code behaves feels authoritative.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you haven’t been following the evolution of React Server Components and frameworks like Next.js: modern React apps now use file-level directives such as &lt;code&gt;'use client'&lt;/code&gt; and &lt;code&gt;'use server'&lt;/code&gt; to control where code runs. They look like simple string literals at the top of a file, but they decide whether a component executes on the server or the client — shaping bundling, rendering and data-flow. That’s where the confusion begins.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But here’s the tension:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directives look like language features.&lt;br&gt;
Directives feel like language features.&lt;br&gt;
Yet directives &lt;em&gt;are&lt;/em&gt; not language features.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They are &lt;strong&gt;tooling-level signals&lt;/strong&gt; — consumed by bundlers, compilers, and build pipelines.&lt;/p&gt;

&lt;p&gt;This misunderstanding is not a new phenomenon.&lt;br&gt;
We’ve been here before.&lt;/p&gt;
&lt;h3&gt;
  
  
  A Personal Flashback
&lt;/h3&gt;

&lt;p&gt;The first time I saw a &lt;code&gt;#pragma once&lt;/code&gt; in a C++ codebase as a young developer, I thought:&lt;br&gt;
“Wow, the language has a keyword for this! Why doesn’t JavaScript?”&lt;/p&gt;

&lt;p&gt;Except… it wasn’t a language keyword.&lt;br&gt;
It was a compiler instruction. A &lt;em&gt;directive&lt;/em&gt;. A hint to the &lt;strong&gt;preprocessor&lt;/strong&gt;, not to the language itself.&lt;/p&gt;

&lt;p&gt;Just like &lt;code&gt;'use strict'&lt;/code&gt; wasn’t “JavaScript syntax” at first — and just like &lt;code&gt;'use client'&lt;/code&gt; isn’t “JavaScript syntax” today.&lt;/p&gt;

&lt;p&gt;This post explores that parallel. Because understanding the &lt;strong&gt;C/C++ preprocessor&lt;/strong&gt; era is a surprisingly powerful way to understand modern JS directives — why they confuse people, and what we could learn from the past to teach them better.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Do Directives Feel Like Language Features?
&lt;/h2&gt;

&lt;p&gt;If you show a newcomer the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and ask them what &lt;code&gt;'use client'&lt;/code&gt; is, most will confidently answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It’s part of JavaScript.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn’t ignorance. It’s &lt;strong&gt;pattern recognition&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Throughout their entire programming life, file-level “magic statements” have almost always been &lt;strong&gt;language semantics&lt;/strong&gt;, not tooling semantics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;"use strict"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;"use asm"&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They look like syntax.&lt;br&gt;
They live at the top of the file.&lt;br&gt;
They change behavior.&lt;/p&gt;

&lt;p&gt;So the brain does the obvious thing: it classifies them as language.&lt;/p&gt;

&lt;p&gt;The TanStack article captures part of this well when it says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A directive at the top of a file looks authoritative. It gives the impression of being a language-level truth, not a framework hint.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the crux of the confusion.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Hidden Mechanism Makes It Worse
&lt;/h3&gt;

&lt;p&gt;Directives blur boundaries because the code that reacts to them is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;invisible&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;non-local&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;not traceable through imports&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;somewhere&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ I can follow the import. I see who owns it. I can version it. I know what documentation to search for.&lt;/p&gt;

&lt;p&gt;But with directives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there is &lt;strong&gt;no import&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;no namespace&lt;/li&gt;
&lt;li&gt;no ownership reference&lt;/li&gt;
&lt;li&gt;no callsite to inspect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The behavior “comes from nowhere”.&lt;/p&gt;

&lt;p&gt;Which is exactly why they &lt;em&gt;feel&lt;/em&gt; like language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Build Tools… and the Illusion Solidifies
&lt;/h3&gt;

&lt;p&gt;Unlike JavaScript keywords, directives do nothing by themselves.&lt;/p&gt;

&lt;p&gt;A runtime engine won’t throw if you mistype &lt;code&gt;'use clinet'&lt;/code&gt;.&lt;br&gt;
A bundler or transform plugin decides what to do with it. Some ignore it, some error, some treat it as a string literal.&lt;/p&gt;

&lt;p&gt;This leads to the second major confusion:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If it requires a bundler to work, isn’t it part of the ecosystem platform, not the language?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From the developer’s perspective, &lt;strong&gt;if code changes behavior without explicit imports&lt;/strong&gt;, the mind defaults to:&lt;/p&gt;

&lt;p&gt;✅ language feature&lt;br&gt;
❌ library feature&lt;/p&gt;

&lt;p&gt;And that is the trap.&lt;/p&gt;

&lt;p&gt;Because what we call “platform” today is actually a &lt;strong&gt;stack of tools&lt;/strong&gt; — not a coherent language surface. Exactly like in the C/C++ era.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Look Back: C/C++ Macros and the Preprocessor
&lt;/h2&gt;

&lt;p&gt;Long before modern JavaScript build pipelines, the C and C++ world lived through a very similar confusion. And it all started with a layer that sat before compilation: the &lt;strong&gt;preprocessor&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To understand today’s directives, we need to briefly revisit three pillars of that era — because they map surprisingly well to what we see today.&lt;/p&gt;
&lt;h3&gt;
  
  
  The C Preprocessor Was Not the Language — But It Felt Like It
&lt;/h3&gt;

&lt;p&gt;Consider this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define PI 3.14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many beginners encountering this for the first time assume:&lt;br&gt;
“Oh, C has a special language keyword for defining constants.”&lt;/p&gt;

&lt;p&gt;Except… &lt;code&gt;#define&lt;/code&gt; is not part of the C language grammar.&lt;br&gt;
It’s an instruction to a separate tool that runs before the compiler.&lt;/p&gt;

&lt;p&gt;It performs text substitution — not type checking, not syntax analysis, not semantic validation.&lt;/p&gt;

&lt;p&gt;Yet, because it lived inside &lt;code&gt;.c/.h&lt;/code&gt; files and looked like “code”, generations of developers perceived it as &lt;strong&gt;the language&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sound familiar?&lt;/p&gt;

&lt;p&gt;A directive in JS behaves the same way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JavaScript engine doesn’t know what that means.&lt;br&gt;
The bundler decides what to &lt;em&gt;rewrite&lt;/em&gt; before execution.&lt;/p&gt;

&lt;p&gt;Both are &lt;strong&gt;pre-language phases&lt;/strong&gt; that masquerade as language.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pragmas: The Original “Framework Directives”
&lt;/h3&gt;

&lt;p&gt;If macros were like today’s codegen utilities, then &lt;code&gt;#pragma&lt;/code&gt; was the closest ancestor to modern directives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#pragma once
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line is not part of the C++ language spec.&lt;br&gt;
It’s a compiler-specific “hint” — an instruction that affects how the build system treats this file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No import&lt;/li&gt;
&lt;li&gt;No namespace or provenance&lt;/li&gt;
&lt;li&gt;No indication of ownership&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Different compilers supported different pragmas. Some ignored them. Some produced warnings. Some behaved differently.&lt;/p&gt;

&lt;p&gt;Replace “compiler” with “bundler” and you get 2025.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js reacts to &lt;code&gt;'use client'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Vite might ignore it&lt;/li&gt;
&lt;li&gt;A custom RSC bundler might interpret it differently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s the same fragmentation pattern seen 30 years ago.&lt;/p&gt;
&lt;h3&gt;
  
  
  Include Guards: The First “Invisible Build-Time Behavior”
&lt;/h3&gt;

&lt;p&gt;Before &lt;code&gt;#pragma once&lt;/code&gt; became common, C/C++ used &lt;strong&gt;include guards&lt;/strong&gt; to prevent double inclusion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#ifndef MY_HEADER_H
#define MY_HEADER_H
&lt;/span&gt;
&lt;span class="c1"&gt;// header contents&lt;/span&gt;

&lt;span class="cp"&gt;#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;altered program behavior&lt;/li&gt;
&lt;li&gt;existed only for tooling&lt;/li&gt;
&lt;li&gt;had no runtime meaning&lt;/li&gt;
&lt;li&gt;required knowledge of the &lt;strong&gt;build model&lt;/strong&gt;, not just the language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;C/C++ forced developers to learn that “code you write in a file” and “the language itself” are not the same thing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was a painful but transformative lesson.&lt;/p&gt;

&lt;p&gt;We are now at the &lt;strong&gt;same educational moment&lt;/strong&gt; in JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Stage Compilation: A Familiar Pipeline
&lt;/h3&gt;

&lt;p&gt;C/C++ had distinct layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Preprocessor → Compiler → Linker → Executable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modern JS tooling has the &lt;strong&gt;same separation&lt;/strong&gt;, just with cooler names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Directive Scanner / Loader → AST Transforms → Bundler → Output Chunks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And just like beginners blamed “C++ the language” for preprocessor quirks, today developers blame:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“JavaScript”&lt;/li&gt;
&lt;li&gt;“React”&lt;/li&gt;
&lt;li&gt;“the platform”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…for behaviors that actually originate from build tooling.&lt;/p&gt;

&lt;p&gt;History is repeating itself — almost line for line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modern Directives Through the Lens of the Preprocessor Era
&lt;/h2&gt;

&lt;p&gt;Once you see the C/C++ parallels, modern JavaScript directives suddenly make a lot more sense. They are not an evolution of JavaScript syntax — they are an evolution of compiler hints.&lt;/p&gt;

&lt;p&gt;Let’s make the mapping explicit:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Preprocessor Era Concept&lt;/th&gt;
&lt;th&gt;Modern JS Equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#pragma&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;'use client'&lt;/code&gt;, &lt;code&gt;'use server'&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;#define&lt;/code&gt; macros&lt;/td&gt;
&lt;td&gt;code transforms / auto-generated wrappers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;#include&lt;/code&gt; guards&lt;/td&gt;
&lt;td&gt;module boundary / hydration boundaries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;compiler-specific behavior&lt;/td&gt;
&lt;td&gt;bundler-specific behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;multi-stage builds&lt;/td&gt;
&lt;td&gt;loader → transform → bundle pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Just like in the 90s, the surface looks deceptively simple — but the real action happens underneath.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directives Don’t Execute — They Instruct a Tool
&lt;/h3&gt;

&lt;p&gt;A key property of directives is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;They don’t do anything &lt;em&gt;themselves&lt;/em&gt; — they only change how something else behaves.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s a breakdown of what typically happens in a directive-driven pipeline (simplified, but accurate enough):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read file → Check for directives → Decide environment / boundary →
Run transforms → Generate client/server bundles → Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s compare that to the C pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read file → Preprocessor expands macros + handles pragmas →
Compile → Link → Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They are &lt;strong&gt;structurally identical concepts&lt;/strong&gt;, just applied to different languages and eras.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the Illusion of a Language Feature Persists
&lt;/h3&gt;

&lt;p&gt;Three psychological factors contribute to the confusion:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;They look like syntax&lt;/strong&gt;&lt;br&gt;
Both &lt;code&gt;#pragma once&lt;/code&gt; and &lt;code&gt;'use client'&lt;/code&gt; feel like reserved keywords.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;They live at the top of the file&lt;/strong&gt;&lt;br&gt;
Anything that shapes the &lt;em&gt;entire file&lt;/em&gt; is often assumed to be language.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;They act globally and implicitly&lt;/strong&gt;&lt;br&gt;
They don’t require instantiation or import.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In other words, directives successfully exploit a &lt;strong&gt;linguistic illusion&lt;/strong&gt;.&lt;br&gt;
They act like a programming language — while not being one.&lt;/p&gt;
&lt;h3&gt;
  
  
  But Modern Directives Go Further Than C Pragmas
&lt;/h3&gt;

&lt;p&gt;Here’s where things get more interesting:&lt;/p&gt;

&lt;p&gt;C pragmas only affected compilation behavior.&lt;br&gt;
Modern directives often affect &lt;strong&gt;execution model, code placement, bundling, and runtime boundaries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;'use server'&lt;/code&gt; might:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;move code into a server-only chunk&lt;/li&gt;
&lt;li&gt;replace calls with RPC stubs&lt;/li&gt;
&lt;li&gt;add serialization wrappers&lt;/li&gt;
&lt;li&gt;enforce data-flow constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is already beyond what the C preprocessor did.&lt;/p&gt;

&lt;p&gt;It’s closer to a &lt;strong&gt;macro system + compiler pass&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Which is exactly why understanding the distinction matters:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If something affects runtime execution and code placement, we should not treat it as “just a string at the top of the file”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And yet, ironically, most misconceptions arise because that is &lt;em&gt;exactly how it appears&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Build Tools Are the Real Interpreter of Directives
&lt;/h3&gt;

&lt;p&gt;Just like different C compilers treated pragmas differently, modern JS tooling varies, too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js interprets &lt;code&gt;'use client'&lt;/code&gt; one way&lt;/li&gt;
&lt;li&gt;Vite + RSC implementations another&lt;/li&gt;
&lt;li&gt;Third-party bundlers a third way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If tomorrow another framework introduced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use streaming-server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript engines wouldn’t care.&lt;br&gt;
Tools would decide what it means.&lt;/p&gt;

&lt;p&gt;And that is the mental shift we need developers to make:&lt;/p&gt;

&lt;p&gt;Directive ≠ language&lt;br&gt;
Directive = build instruction&lt;/p&gt;

&lt;p&gt;They live in userland — not in the spec.&lt;/p&gt;

&lt;p&gt;Before we move on, it’s worth pausing for a moment. The parallels with C and C++ are useful for understanding the shape of directives, but they can still feel abstract until you’ve seen them in practice. To bring the idea into clearer focus, let’s look at a concrete example from today’s ecosystem — one that makes the theory a bit more tangible, and shows how these compiler hints manifest in real, modern code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📦 &lt;strong&gt;When Inline Server Functions Reveal the Need for Directives&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I once ran into a case that perfectly exposed why some server behaviors cannot be left to runtime.&lt;/p&gt;

&lt;p&gt;Consider an inline server function defined inside a Server Component, capturing variables from its local scope:&lt;/p&gt;


&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Dashboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.27&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ← captures "rate" from the component scope&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;At first glance, this feels like a normal function call. But for this to work, the bundler must do something subtle and non-negotiable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detect that save is a server function,&lt;/li&gt;
&lt;li&gt;hoist it into a server-only module,&lt;/li&gt;
&lt;li&gt;perform AST-level closure analysis to capture rate,&lt;/li&gt;
&lt;li&gt;and generate a stable, directly callable reference for the client — not a runtime-constructed wrapper.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A runtime helper cannot solve this.&lt;br&gt;
By the time the code runs, the closure is gone and the intent is already lost.&lt;br&gt;
The function must be transformed before the program exists, so that the client can call it as a direct function, not a proxy we stitched together too late.&lt;/p&gt;

&lt;p&gt;This is why directives fit this space so well: they tell the build tools at the moment of definition what this function truly is, giving them time to shape it accordingly.&lt;/p&gt;

&lt;p&gt;Some decisions must happen while the code is still being woven — not after it is already alive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Educational Gap — and What We Can Learn From History
&lt;/h2&gt;

&lt;p&gt;If you step back and look at the confusion around directives today, you’ll notice something striking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The problem is no longer technical — it’s educational.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We’ve repeated a historical pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A tool-level construct &lt;strong&gt;looks&lt;/strong&gt; like language&lt;/li&gt;
&lt;li&gt;Developers assume it is language&lt;/li&gt;
&lt;li&gt;The mental model becomes wrong&lt;/li&gt;
&lt;li&gt;Confusion spreads faster than documentation can correct it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This happened with the C preprocessor.&lt;br&gt;
It’s happening again with JavaScript directives.&lt;/p&gt;

&lt;h3&gt;
  
  
  We Need to Teach the Layering — Not Just the Feature
&lt;/h3&gt;

&lt;p&gt;If we teach &lt;code&gt;'use server'&lt;/code&gt; as:&lt;/p&gt;

&lt;p&gt;“This makes your function run on the server.”&lt;/p&gt;

&lt;p&gt;…we’ve already lost.&lt;/p&gt;

&lt;p&gt;Because that sentence hides 4 separate layers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Responsible For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Syntax&lt;/td&gt;
&lt;td&gt;writing a string literal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Loader&lt;/td&gt;
&lt;td&gt;detecting the directive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build tools&lt;/td&gt;
&lt;td&gt;transforming / splitting code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;enforcing the boundary&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If developers don’t understand which layer is responsible for what, they will blame “JavaScript” for a bundler problem — just like C developers once blamed “the language” for preprocessor bugs.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the C/C++ Community Eventually Learned
&lt;/h3&gt;

&lt;p&gt;Over time, C/C++ education evolved:&lt;/p&gt;

&lt;p&gt;Early teaching:&lt;br&gt;
“Here’s how to use &lt;code&gt;#define&lt;/code&gt; and &lt;code&gt;#pragma&lt;/code&gt;.”&lt;/p&gt;

&lt;p&gt;Mature teaching:&lt;br&gt;
“Here’s what the &lt;strong&gt;preprocessor&lt;/strong&gt; is, and why it’s separate from the language.”&lt;/p&gt;

&lt;p&gt;After that shift, confusion dropped dramatically. No serious C++ course today teaches macros without first teaching the &lt;strong&gt;mental model&lt;/strong&gt; of the compilation stages.&lt;/p&gt;

&lt;p&gt;We need the same shift for JS directives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directives Aren’t Bad — They’re Powerful, If Understood
&lt;/h3&gt;

&lt;p&gt;This post is not an argument against directives. They serve a purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conveying intent declaratively&lt;/li&gt;
&lt;li&gt;Reducing boilerplate&lt;/li&gt;
&lt;li&gt;Helping tools optimize and separate code&lt;/li&gt;
&lt;li&gt;Giving the developer a simple switch for complex behaviors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fact, some of the most ergonomic server/serverless features would be far more cumbersome without them.&lt;/p&gt;

&lt;p&gt;But the price of ergonomics is &lt;strong&gt;clarity debt&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If we don’t teach where the magic comes from, developers misattribute the source of truth — and debugging collapses.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Simple Mental Model to Teach (Starting Tomorrow)
&lt;/h3&gt;

&lt;p&gt;I like to explain directives with a single sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A directive is a note you leave for your build tools — not for JavaScript.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That line alone fixes 70% of misunderstandings.&lt;/p&gt;

&lt;p&gt;Add one analogy:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If &lt;code&gt;#pragma once&lt;/code&gt; was not C++ syntax, then &lt;code&gt;'use client'&lt;/code&gt; is not JavaScript syntax either.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And suddenly, people get it.&lt;/p&gt;

&lt;p&gt;This doesn’t require more docs — it requires better &lt;strong&gt;framing&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Step Toward Clarity: A TypeScript Plugin for Directives
&lt;/h2&gt;

&lt;p&gt;Before wrapping up, I want to share one more concrete step I took to reduce this confusion in real-world codebases. If part of the problem comes from directives &lt;em&gt;looking&lt;/em&gt; like language yet lacking any formal structure, then giving them &lt;strong&gt;type-level meaning&lt;/strong&gt; is one way to bridge the gap.&lt;/p&gt;

&lt;p&gt;I built a small TypeScript plugin called &lt;code&gt;typescript-plugin-directives&lt;/code&gt; that brings &lt;em&gt;type safety and IntelliSense awareness&lt;/em&gt; to directives. It allows teams to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;define their own directive vocabulary,&lt;/li&gt;
&lt;li&gt;validate them at compile time,&lt;/li&gt;
&lt;li&gt;get editor hints and autocomplete,&lt;/li&gt;
&lt;li&gt;and avoid silent typos like &lt;code&gt;'use clinet'&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal isn’t to “standardize” directives, but to &lt;strong&gt;make their intent explicit and visible to both developers and tooling&lt;/strong&gt; — without needing a bundler to interpret them first.&lt;/p&gt;

&lt;p&gt;You can try it here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;npm&lt;/strong&gt;: &lt;a href="https://www.npmjs.com/package/typescript-plugin-directives" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/typescript-plugin-directives&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/lazarv/typescript-plugin-directives" rel="noopener noreferrer"&gt;https://github.com/lazarv/typescript-plugin-directives&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s intentionally lightweight — just a small layer to help the mental model click earlier, and to give directives a more formal shape inside TypeScript projects.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There’s a common assumption that a TypeScript plugin could “enforce” directives — that if the plugin knows about them, the system becomes safe by default.&lt;br&gt;
But a TS plugin lives in the Language Service. It can provide awareness, warnings, and guidance — yet it still doesn’t run where code is actually transformed. It doesn’t participate in compilation or bundling.&lt;/p&gt;

&lt;p&gt;A plugin can help identify directive usage, but &lt;strong&gt;it cannot enforce their semantics&lt;/strong&gt;.&lt;br&gt;
For that, the compiler needs a signal of intent — something the type system can understand.&lt;/p&gt;

&lt;p&gt;To enable this, I expose a global &lt;code&gt;Directive&lt;/code&gt; type in my plugin. Authors can use &lt;code&gt;satisfies&lt;/code&gt; not to inform the editor, but to inform the &lt;strong&gt;TypeScript compiler&lt;/strong&gt; that a given string is intended to be a directive:&lt;/p&gt;


&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This doesn’t change behavior or trigger any transformation.&lt;br&gt;
What it does is far simpler and more fundamental:&lt;/p&gt;

&lt;p&gt;It tells the type system:&lt;br&gt;
&lt;strong&gt;“Treat this as a directive — and validate it as such.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It aligns intent with the compiler, not with runtime, and not only with the IDE.&lt;/p&gt;

&lt;p&gt;The actual separation of worlds — hoisting inline server functions out of a component, analyzing captured scope, generating a directly callable boundary — still belongs entirely to the build. The type system can acknowledge intent, but the bundler is the one who must act on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One practical caveat:&lt;/strong&gt; today, some tooling — including Next.js — expects directives to appear as &lt;em&gt;bare string literals&lt;/em&gt;. When written as &lt;code&gt;'use server' satisfies Directive&lt;/code&gt;, the directive may no longer be detected, since the literal is no longer in the exact form the framework scans for. Until this changes, this pattern won’t be picked up by Next.js.&lt;/p&gt;

&lt;p&gt;There is one more subtlety worth mentioning. This type-level intent only matters if a type-checker is actually running. Many modern toolchains — esbuild, SWC, Oxc, Bun, even most Deno and Vite setups — do not type-check at all. They simply strip types and move on. In those environments, the &lt;code&gt;Directive&lt;/code&gt; + &lt;code&gt;satisfies&lt;/code&gt; expression becomes a silent note to the compiler that never had a chance to listen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Closing Reflection
&lt;/h3&gt;

&lt;p&gt;The article from Tanner raises a valuable conversation — one worth having early, before bad habits ossify. I don’t believe the goal should be to eliminate directives; they clearly solve real problems. But we &lt;em&gt;can&lt;/em&gt; learn from history, and avoid the confusion that entire generations of C/C++ developers had to unlearn.&lt;/p&gt;

&lt;p&gt;We’ve been here before.&lt;br&gt;
We know how this story goes.&lt;br&gt;
This time, we can skip the decade of confusion in the middle.&lt;/p&gt;

&lt;p&gt;Teach the layers.&lt;br&gt;
Teach the provenance.&lt;br&gt;
Teach the mental model.&lt;/p&gt;

&lt;p&gt;And directives will stop feeling like “secret language features” — and start feeling like the powerful, intentional compiler hints they actually are.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>nextjs</category>
      <category>react</category>
      <category>reactserver</category>
    </item>
    <item>
      <title>Exploring an experimental Micro-Frontend Architecture with Server-Side Rendering using React Server Components</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Sun, 25 Aug 2024 12:18:46 +0000</pubDate>
      <link>https://forem.com/lazarv/exploring-an-experimental-micro-frontend-architecture-with-server-side-rendering-using-react-server-components-2d0f</link>
      <guid>https://forem.com/lazarv/exploring-an-experimental-micro-frontend-architecture-with-server-side-rendering-using-react-server-components-2d0f</guid>
      <description>&lt;p&gt;&lt;a id="introduction"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;What are Micro-Frontends?&lt;/li&gt;
&lt;li&gt;Introduction to React Server Components (RSC)&lt;/li&gt;
&lt;li&gt;The Experimental Architecture: Combining Micro-Frontends with RSC&lt;/li&gt;
&lt;li&gt;Challenges and Considerations&lt;/li&gt;
&lt;li&gt;The Future of Micro-Frontends with RSC&lt;/li&gt;
&lt;li&gt;Introducing &lt;code&gt;@lazarv/react-server&lt;/code&gt; with RSC Delegation&lt;/li&gt;
&lt;li&gt;Implementing the Experimental Micro-Frontend Architecture with &lt;code&gt;@lazarv/react-server&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Supporting Client Components in a Micro-Frontend Architecture&lt;/li&gt;
&lt;li&gt;Implementing Server Actions in a Micro-Frontend Architecture&lt;/li&gt;
&lt;li&gt;Using Static Site Generation in a Micro-Frontend Architecture&lt;/li&gt;
&lt;li&gt;Server Islands: loading MFE content using &lt;code&gt;ReactServerComponent&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Shared State Management in a Micro-Frontend Architecture&lt;/li&gt;
&lt;li&gt;Leveraging Native ES Modules with &lt;code&gt;@lazarv/react-server&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In recent years, the micro-frontend architecture has gained significant traction, enabling teams to independently develop and deploy features within a larger application. This paradigm empowers organizations to scale development efforts by decentralizing codebases and fostering collaboration across teams. Coupled with server-side rendering (SSR), micro-frontends offer enhanced performance and SEO capabilities. In this blog post, we'll explore an experimental architecture that marries micro-frontends with React Server Components (RSC), pushing the boundaries of what's possible in modern web development.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Micro-Frontends?
&lt;/h2&gt;

&lt;p&gt;&lt;a id="what-are-micro-frontends"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Micro-frontends extend the concept of micro-services to the frontend, where a large application is broken down into smaller, independently deployable pieces. Each micro-frontend can be built and maintained by different teams, possibly using different technologies. This approach allows teams to work in parallel without stepping on each other's toes, thus accelerating the development process and making the codebase more maintainable over time.&lt;/p&gt;

&lt;p&gt;However, this flexibility comes with its own set of challenges. Ensuring consistency in user experience, managing shared state, and optimizing performance across micro-frontends are some of the significant hurdles that developers face.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does This Stack Up?
&lt;/h3&gt;

&lt;p&gt;When considering alternative approaches like traditional monolithic applications or Single Page Applications (SPAs), the micro-frontend architecture offers superior scalability and team autonomy. Unlike monoliths, which can become unwieldy as they grow, micro-frontends allow teams to iterate on specific features independently. Compared to SPAs, this architecture provides better initial load performance through SSR, which is crucial for applications with SEO requirements or those targeting low-bandwidth environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to React Server Components (RSC)
&lt;/h2&gt;

&lt;p&gt;&lt;a id="introduction-to-rsc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React Server Components (RSC) is a new feature of React that allows components to be rendered on the server. Unlike traditional SSR, where HTML is generated on the server, React Server Components can return lightweight "descriptions" of UI components, which the client can then render.&lt;/p&gt;

&lt;p&gt;This approach has several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Improved Performance:&lt;/strong&gt; By offloading some rendering logic to the server, the client-side workload is reduced, leading to faster interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code-Splitting at a Component Level:&lt;/strong&gt; RSC facilitates finer-grained code-splitting, allowing for only the necessary components to be loaded and rendered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Developer Experience:&lt;/strong&gt; The seamless integration of server and client components allows for a smoother development experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Experimental Architecture: Combining Micro-Frontends with RSC
&lt;/h2&gt;

&lt;p&gt;&lt;a id="combining-mfe-with-rsc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our experimental architecture attempts to leverage the strengths of both micro-frontends and React Server Components. Here's an overview of the key components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Independent Micro-Frontend Applications:&lt;/strong&gt; Each micro-frontend is developed as a standalone application. These applications can be written in different frameworks or technologies but are integrated using a common interface or shared protocol.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-Side Rendering with React Server Components:&lt;/strong&gt; The server takes responsibility for rendering React Server Components, returning lightweight component descriptions to the client. This reduces the initial load time and provides a smoother user experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shared State Management:&lt;/strong&gt; To ensure consistency across micro-frontends, a shared state management layer is introduced. This layer allows for state synchronization and communication between different micro-frontends, even if they are built using different technologies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lazy Loading and Code Splitting:&lt;/strong&gt; RSC enables lazy loading of components at a granular level, ensuring that only the necessary code is sent to the client. This optimizes performance and reduces the time to interactive (TTI).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Challenges and Considerations
&lt;/h2&gt;

&lt;p&gt;&lt;a id="challenges-and-considerations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While this architecture offers significant benefits, it is not without its challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; The integration of micro-frontends with React Server Components adds a layer of complexity. Teams must be diligent in managing dependencies, ensuring compatibility, and maintaining a consistent user experience across micro-frontends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Overhead:&lt;/strong&gt; Although server-side rendering improves the initial load time, it can introduce performance overhead on the server. Proper load balancing and caching strategies are crucial to mitigate this issue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SEO and Accessibility:&lt;/strong&gt; While SSR improves SEO, developers need to ensure that all micro-frontends adhere to best practices for SEO and accessibility, particularly in a mixed technology environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shared Dependencies:&lt;/strong&gt; Managing shared dependencies across micro-frontends can be challenging. Ensuring that different versions of libraries or frameworks do not conflict is crucial to maintaining application stability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future of Micro-Frontends with RSC
&lt;/h2&gt;

&lt;p&gt;&lt;a id="future-of-mfe-with-rsc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This experimental architecture is just one possible way to harness the power of micro-frontends and React Server Components. As these technologies evolve, we can expect to see more refined patterns and best practices emerge. For now, this approach represents an exciting frontier in web development, offering the potential for highly scalable, performant, and maintainable applications.&lt;/p&gt;

&lt;p&gt;By combining micro-frontends with React Server Components, we can create applications that are not only modular and scalable but also optimized for performance and user experience. However, careful consideration must be given to the inherent complexity and potential pitfalls of this approach.&lt;/p&gt;

&lt;p&gt;To illustrate a potential real-world use case, consider a large e-commerce platform that needs to scale while maintaining high performance. Using the micro-frontend architecture with React Server Components, each part of the application, such as the product catalog, user reviews, and checkout process, could be developed, deployed, and updated independently. This modular approach allows teams to work on different features simultaneously, reduces the risk of errors during deployment, and improves load times through server-side rendering, ultimately enhancing the user experience and streamlining maintenance.&lt;/p&gt;

&lt;p&gt;As always, the best architecture is one that fits your specific use case. If you're considering adopting this experimental approach, weigh the pros and cons carefully and consider starting with a proof of concept to validate your ideas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing &lt;code&gt;@lazarv/react-server&lt;/code&gt; with RSC Delegation
&lt;/h2&gt;

&lt;p&gt;&lt;a id="rsc-delegation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@lazarv/react-server&lt;/code&gt; is a cutting-edge framework designed to streamline the development of micro-frontends with robust server-side rendering capabilities. One of the standout features of this framework is its support for React Server Components (RSC), enabling developers to efficiently manage server-side logic while maintaining a seamless user experience. However, what truly sets &lt;code&gt;@lazarv/react-server&lt;/code&gt; apart is its brand-new feature, &lt;strong&gt;RSC Delegation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RSC Delegation&lt;/strong&gt; is a powerful mechanism that allows developers to delegate specific React Server Components to different micro-frontends or even entirely separate servers. This feature ensures that complex or resource-intensive components can be processed on dedicated servers, optimizing performance and scalability. For instance, if one micro-frontend in your application requires heavy data processing, you can delegate that component's execution to a specialized server, leaving the rest of your application to run smoothly.&lt;/p&gt;

&lt;p&gt;By using &lt;strong&gt;RSC Delegation&lt;/strong&gt;, &lt;code&gt;@lazarv/react-server&lt;/code&gt; enables a more modular and flexible architecture, where each micro-frontend can handle its own server-side rendering tasks independently or delegate them as needed. This not only improves the overall performance of your application but also simplifies the development process, as each component can be optimized for its specific environment without impacting the rest of the system. This feature makes &lt;code&gt;@lazarv/react-server&lt;/code&gt; an even more powerful tool for building scalable, maintainable web applications.&lt;/p&gt;

&lt;p&gt;Check out more about &lt;code&gt;@lazarv/react-server&lt;/code&gt; at &lt;a href="https://react-server.dev" rel="noopener noreferrer"&gt;https://react-server.dev&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the Experimental Micro-Frontend Architecture with &lt;code&gt;@lazarv/react-server&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a id="implementing-mfe-with-react-server"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we've discussed the theoretical aspects and potential benefits of combining micro-frontends with React Server Components, it's time to dive into a practical implementation. For this, we'll be using the &lt;code&gt;@lazarv/react-server&lt;/code&gt; framework — a powerful tool designed specifically for server-side rendering with React Server Components.&lt;/p&gt;

&lt;p&gt;This section will guide you through setting up and implementing this architecture using &lt;code&gt;@lazarv/react-server&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;@lazarv/react-server&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;First, you'll need to install the &lt;code&gt;@lazarv/react-server&lt;/code&gt; package. You can do this via pnpm, npm or even yarn. For this example project, we’ll be utilizing pnpm, a fast and efficient package manager that’s particularly well-suited for managing dependencies in complex, multi-project environments like micro-frontends.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
pnpm init
pnpm add @lazarv/react-server 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will add the &lt;code&gt;@lazarv/react-server&lt;/code&gt; package to your project, leveraging pnpm's efficient dependency management system to ensure that your &lt;code&gt;node_modules&lt;/code&gt; folder is optimized and free of duplicates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the Hosting Application
&lt;/h3&gt;

&lt;p&gt;We’ll start by creating a hosting application that will serve as the main entry point for rendering and orchestrating different micro-frontends.&lt;/p&gt;

&lt;p&gt;Create a simple React Server Component that will be rendered on the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./index.jsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HostingApplication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to the Hosting Application&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is a simple React Server Component.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With everything set up, you can run the hosting application directly using the &lt;code&gt;react-server&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm react-server ./index.jsx &lt;span class="nt"&gt;--open&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will start the development server on &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; and automatically open the hosting application in your default web browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Simple Micro-Frontend (MFE) Application
&lt;/h3&gt;

&lt;p&gt;Next, we’ll create a small micro-frontend application that can be loaded into the hosting application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./remote.jsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MFE&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is the Micro-Frontend Component&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loaded from the MFE application.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the MFE application server on port 3001 and open the RSC in the browser using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm react-server ./remote.jsx &lt;span class="nt"&gt;--port&lt;/span&gt; 3001 &lt;span class="nt"&gt;--open&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using &lt;code&gt;RemoteComponent&lt;/code&gt; to integrate the MFE Application into the Hosting Application
&lt;/h3&gt;

&lt;p&gt;Finally, we’ll integrate the MFE into the hosting application by using &lt;code&gt;RemoteComponent&lt;/code&gt; from &lt;code&gt;@lazarv/react-server/router&lt;/code&gt; to load the MFE dynamically.&lt;/p&gt;

&lt;h4&gt;
  
  
  Update the Hosting Application to use &lt;code&gt;RemoteComponent&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Modify the &lt;code&gt;HostingApplication&lt;/code&gt; component to include the &lt;code&gt;RemoteComponent&lt;/code&gt; pointing to &lt;a href="http://localhost:3001:" rel="noopener noreferrer"&gt;http://localhost:3001:&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./index.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RemoteComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lazarv/react-server/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HostingApplication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to the Hosting Application&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is a simple React Server Component.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RemoteComponent&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3001"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, the &lt;code&gt;RemoteComponent&lt;/code&gt; will fetch the RSC payload from the MFE application running on &lt;a href="http://localhost:3001" rel="noopener noreferrer"&gt;http://localhost:3001&lt;/a&gt; and render it within the hosting application using server-side rendering.&lt;/p&gt;

&lt;p&gt;With both the hosting and MFE applications running, you can now test how they work together. The hosting application will dynamically load and display components from the MFE application, allowing you to see how they integrate in real-time. This setup lets you check if everything is functioning correctly and ensure that the micro-frontends are interacting as expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up &lt;code&gt;package.json&lt;/code&gt; scripts
&lt;/h3&gt;

&lt;p&gt;Let's add &lt;code&gt;run-p&lt;/code&gt;, a utility from &lt;code&gt;npm-run-all&lt;/code&gt; that allows you to run multiple npm scripts in parallel. We will also add a script in the &lt;code&gt;package.json&lt;/code&gt; file to start both the hosting and MFE applications simultaneously, while only opening the hosting application in the browser.&lt;/p&gt;

&lt;p&gt;First, navigate to your project’s root directory and install the &lt;code&gt;npm-run-all&lt;/code&gt; package, which includes the &lt;code&gt;run-p&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; npm-run-all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you'll update the package.json file to include the scripts for starting both applications. Here’s how you can do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev:host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server ./index.jsx --name host --open"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev:remote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server ./remote.jsx --name remote --port 3001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run-p dev:host dev:remote"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@lazarv/react-server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.0-experimental-a6c271a-20240825-5a3908ae"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"npm-run-all"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.1.5"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  In this setup:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;dev:host:&lt;/strong&gt; Starts the development server of the hosting application and opens it in the default browser. The &lt;code&gt;--name host&lt;/code&gt; argument prefixes the server logs with "host" for easier identification in the terminal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;dev:remote:&lt;/strong&gt; Starts the development server of the MFE application on port 3001. The &lt;code&gt;--name remote&lt;/code&gt; argument prefixes the logs with "remote" for clarity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;dev:&lt;/strong&gt; Uses &lt;code&gt;run-p&lt;/code&gt; to run both &lt;code&gt;dev:host&lt;/code&gt; and &lt;code&gt;dev:remote&lt;/code&gt; in parallel, ensuring both servers start simultaneously but only the hosting application opens in the browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Running the applications
&lt;/h3&gt;

&lt;p&gt;To start both the hosting and MFE applications with the appropriate logging prefixes, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will start both servers concurrently. The hosting application will be accessible on &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, and the MFE application will be on &lt;a href="http://localhost:3001" rel="noopener noreferrer"&gt;http://localhost:3001&lt;/a&gt;. Only the hosting application will open automatically in the browser, while logs from both applications will be prefixed with "host" and "remote" respectively for clear identification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supporting Client Components in a Micro-Frontend Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a id="client-components-in-mfe"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a micro-frontend setup, client components play a crucial role in maintaining the balance between server-rendered content and client-side interactivity. With React's new "use client" directive, client components are still rendered on the server side, ensuring that the initial content is available as quickly as possible. Once the content is sent to the browser, these components are hydrated, which enables their interactivity, such as handling user input, managing state, and responding to events.&lt;/p&gt;

&lt;p&gt;By incorporating client components into a micro-frontend architecture, you ensure that each micro-frontend not only contributes to the overall performance and SEO of the application but also provides a rich, interactive experience for users. This dual-rendering capability allows developers to choose the right balance of server-side rendering and client-side interactivity, depending on the needs of each component.&lt;/p&gt;

&lt;p&gt;We will demonstrate how to integrate client components into a micro-frontend architecture using &lt;code&gt;@lazarv/react-server&lt;/code&gt;. Specifically, we’ll create a new micro-frontend application that includes a client-side counter component, showing how it can be seamlessly integrated into an existing hosting application. This example will highlight the flexibility and power of combining server-rendered and client-rendered components within a unified architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a new MFE application with a counter
&lt;/h3&gt;

&lt;p&gt;Next, we'll create a simple counter component that will be the MFE application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./counter.jsx&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CounterComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Counter Component&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Current Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increment&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Decrement&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component uses React's &lt;code&gt;useState&lt;/code&gt; hook to keep track of the count and provides two buttons to increment and decrement the count.&lt;/p&gt;

&lt;p&gt;To differentiate from the previous MFE, we’ll run this new MFE on port 3002.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm react-server ./counter.jsx &lt;span class="nt"&gt;--port&lt;/span&gt; 3002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a script to the &lt;code&gt;package.json&lt;/code&gt; file to start this new MFE application and also update the &lt;code&gt;dev&lt;/code&gt; script to concurrently run the MFE counter application too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev:counter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server ./counter.jsx --port 3002 --name counter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run-p dev:host dev:remote dev:counter"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can run the MFE counter application using the following command too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm dev:counter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integrate the Counter MFE Application into the Hosting Application
&lt;/h3&gt;

&lt;p&gt;Finally, let's integrate this new MFE into the existing hosting application.&lt;/p&gt;

&lt;p&gt;Modify the &lt;code&gt;HostingApplication&lt;/code&gt; component to include the new &lt;code&gt;RemoteComponent&lt;/code&gt; for the counter MFE:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./index.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RemoteComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lazarv/react-server/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HostingApplication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to the Hosting Application&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is a simple React Server Component.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RemoteComponent&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3001"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RemoteComponent&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3002"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, the hosting application will load both the original MFE and the new counter MFE, displaying them on the same page.&lt;/p&gt;

&lt;p&gt;Start the hosting application along with the counter MFE application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this does not work yet! We need to add an import map to resolve the client-side issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is an Import Map?
&lt;/h3&gt;

&lt;p&gt;When working with native ES modules in modern browsers, an import map is a powerful tool that helps you control the way your JavaScript modules are resolved and loaded. By default, when you use the import statement in your code, the browser looks for modules based on their paths or URLs. However, this can become cumbersome when dealing with complex dependencies or when you want to use specific versions of a library without changing all your imports.&lt;/p&gt;

&lt;p&gt;An import map allows you to define custom mappings for module specifiers, essentially telling the browser where to find specific modules. This is particularly useful when you're working with libraries or frameworks that are hosted on a CDN, or when you want to maintain control over the version of a module being used across your project.&lt;/p&gt;

&lt;p&gt;Here's how an import map works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Module Specifier Mapping:&lt;/strong&gt; With an import map, you can map a module specifier (the string you use in the import statement) to a specific URL. This means you can use simple names like &lt;code&gt;react&lt;/code&gt; or &lt;code&gt;lodash&lt;/code&gt; in your imports, and the browser will know exactly where to find them based on your map.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Version Control:&lt;/strong&gt; Import maps allow you to lock your dependencies to specific versions without needing to modify each import statement manually. For example, you can ensure that all references to a library like &lt;code&gt;lodash&lt;/code&gt; point to the same version, which is crucial for maintaining consistency across your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplified Imports:&lt;/strong&gt; Instead of dealing with long, complex URLs or paths, you can keep your import statements clean and easy to read. The import map handles the complexity under the hood.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, import maps are a powerful way to manage module resolution in the browser, making it easier to handle dependencies, control versions, and keep your codebase clean and maintainable when using native ES modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Import map definition
&lt;/h3&gt;

&lt;p&gt;To ensure that only a single instance of React is loaded in the browser when working with multiple micro-frontends, it's important to set up an import map. This prevents issues related to having multiple React instances, such as conflicts in state management or hooks not working correctly. Here's how you can add an import map to your project.&lt;/p&gt;

&lt;p&gt;To properly support an import map and ensure that only a single instance of React is loaded across your micro-frontend architecture, you can configure the framework by using a &lt;code&gt;react-server.config.mjs&lt;/code&gt; file. Below is an explanation and a step-by-step guide to implementing this configuration.&lt;/p&gt;

&lt;p&gt;In your project, create a &lt;code&gt;react-server.config.mjs&lt;/code&gt; file. This file will be used to define how modules are resolved and shared across different parts of your application.&lt;/p&gt;

&lt;p&gt;Add the following content to &lt;code&gt;react-server.config.mjs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;importMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react@0.0.0-experimental-58af67a8f8-20240628?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/jsx-dev-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react@0.0.0-experimental-58af67a8f8-20240628/jsx-dev-runtime?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react-dom@0.0.0-experimental-58af67a8f8-20240628?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react-dom@0.0.0-experimental-58af67a8f8-20240628/client?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server-dom-webpack/client.browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react-server-dom-webpack@0.0.0-experimental-58af67a8f8-20240628/client.browser?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3002/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/jsx-dev-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/jsx-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server-dom-webpack/client.browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The import map is a JSON structure that tells the browser where to find specific modules. In this case, we're specifying that React and related packages should be loaded from &lt;a href="https://esm.sh" rel="noopener noreferrer"&gt;esm.sh&lt;/a&gt;, a popular CDN for ES modules while it can also translate CommonJS packages to native ES modules.&lt;/p&gt;

&lt;p&gt;By pointing to &lt;a href="https://esm.sh" rel="noopener noreferrer"&gt;esm.sh&lt;/a&gt;, all micro-frontends and the hosting application will download and use the same instance of React and related modules directly from the CDN on the client-side. This avoids the common issue of having multiple versions of React in the same application, which can cause hooks to break and state to behave unexpectedly.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;resolve.shared&lt;/code&gt; section ensures that specific modules are shared across all components and micro-frontends, preventing multiple instances from being loaded. This guarantees that any part of your application that imports React, ReactDOM, or related libraries will use the same shared instance from esm.sh.&lt;/p&gt;

&lt;p&gt;Now with the import map defined, we can retry running the apps by using &lt;code&gt;pnpm dev&lt;/code&gt; and it should work now with the counter component working inside the hosting application!&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Server Actions in a Micro-Frontend Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a id="server-actions-in-mfe"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Server actions in a micro-frontend architecture represent a powerful pattern for managing server-side logic in a modular and secure way. By defining server actions within individual micro-frontends, developers can keep the server-side operations close to the components that need them, maintaining a clean separation of concerns and enhancing scalability.&lt;/p&gt;

&lt;p&gt;In a typical micro-frontend setup, different parts of the application are developed and deployed independently, each potentially containing its own server-side logic. Server actions enable each micro-frontend to manage its own server-side tasks, such as handling form submissions, interacting with databases, or processing data. These actions are executed entirely on the server, ensuring that sensitive logic is not exposed to the client, which greatly enhances security.&lt;/p&gt;

&lt;p&gt;Moreover, by using server actions within micro-frontends, developers can optimize performance by offloading computationally expensive tasks to the server. This reduces the load on the client, resulting in a more responsive user interface. Since server actions are tied to specific components, they also contribute to a modular architecture where each micro-frontend can be developed, tested, and scaled independently of the others.&lt;/p&gt;

&lt;p&gt;Overall, server actions in a micro-frontend architecture allow for a robust, scalable, and secure application structure. They empower each micro-frontend to independently handle its own server-side logic, while still contributing to a cohesive and unified user experience across the entire application.&lt;/p&gt;

&lt;p&gt;Read more about server actions in the React documentation at &lt;a href="https://react.dev/reference/rsc/server-actions" rel="noopener noreferrer"&gt;https://react.dev/reference/rsc/server-actions&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Server Actions with &lt;code&gt;@lazarv/react-server&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now we will implement another MFE application including a form and we will use a server action to handle form submission while staying in the context of the MFE application even when using the hosting application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a new MFE application with a form and a server action
&lt;/h3&gt;

&lt;p&gt;Next, we'll create an RSC component including a form element and we will handle the form submit action using a server action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./form.jsx&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ServerActionComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Anonymous&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Submit"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to the previous counter MFE, we’ll run this new MFE on another a new port again, let's use port 3003 for this one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm react-server ./form.jsx &lt;span class="nt"&gt;--port&lt;/span&gt; 3003
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, add a script to the package.json file to start this new MFE application and also update the &lt;code&gt;dev&lt;/code&gt; script to concurrently run the MFE counter application too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev:form"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server ./form.jsx --port 3003 --cors --name form"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run-p dev:host dev:remote dev:counter dev:form"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can run the MFE application using a server action by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm dev:form
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integrate the server action driven MFE into the Hosting Application
&lt;/h3&gt;

&lt;p&gt;Finally, let's integrate this new MFE using a server action into the existing hosting application.&lt;/p&gt;

&lt;p&gt;Modify the &lt;code&gt;HostingApplication&lt;/code&gt; to include the new &lt;code&gt;RemoteComponent&lt;/code&gt; for the form MFE:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./index.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RemoteComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lazarv/react-server/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HostingApplication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to the Hosting Application&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is a simple React Server Component.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RemoteComponent&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3001"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RemoteComponent&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3002"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RemoteComponent&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3003"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, the hosting application will load all of our MFE applications displaying them on the same page.&lt;/p&gt;

&lt;p&gt;Start the hosting application along with the counter MFE application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using a micro-frontend (MFE) application with a server action in the hosting application allows for a seamless and integrated approach to managing server-side logic across different parts of an application. In this setup, each micro-frontend can independently execute server actions, such as processing data or interacting with a database, while being part of a larger, cohesive system. The hosting application orchestrates these micro-frontends, ensuring they work together harmoniously, while the server actions keep sensitive logic secure and optimize performance by handling complex operations on the server. This approach enhances modularity, scalability, and maintainability, allowing the application to grow and evolve efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Static Site Generation in a Micro-Frontend Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a id="ssg-in-mfe"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To incorporate Static Site Generation (SSG) into your micro-frontend (MFE) architecture using &lt;code&gt;@lazarv/react-server&lt;/code&gt;, we can configure one of the micro-frontends to generate static content at build time. This content will then be served as part of the production build. By using the "remote" flag for the root path, we ensure that the MFE's content is statically generated and included in the hosting application.&lt;/p&gt;

&lt;p&gt;Here’s how to extend the existing example to include SSG for one of the micro-frontends:&lt;/p&gt;

&lt;h3&gt;
  
  
  Update the &lt;code&gt;react-server.config.mjs&lt;/code&gt; for SSG
&lt;/h3&gt;

&lt;p&gt;To enable SSG, you'll need to update the &lt;code&gt;react-server.config.mjs&lt;/code&gt; configuration to specify that the root path of the first MFE should be statically generated with the "remote" flag. This ensures that the content is pre-rendered at build time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;importMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Specify the root path&lt;/span&gt;
        &lt;span class="na"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Enable the "remote" flag for MFE SSG&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build the Micro-Frontend and Hosting Applications for production
&lt;/h3&gt;

&lt;p&gt;Since SSG is only applicable in a production environment, you'll need to build your applications for production. Add the necessary build scripts in your package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build:host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server build ./index.jsx --outDir .react-server --no-export"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build:remote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server build ./remote.jsx --outDir .react-server-remote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build:counter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server build ./counter.jsx --outDir .react-server-counter --no-export"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build:form"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server build ./form.jsx --outDir .react-server-form --no-export"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run-s build:host build:remote build:counter build:form"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start:host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server start --outDir .react-server --port 3000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start:remote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server start --outDir .react-server-remote --port 3001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start:counter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server start --outDir .react-server-counter --port 3002 --cors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start:form"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server start --outDir .react-server-form --port 3003 --cors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run-p start:host start:remote start:counter start:form"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We instruct each build to use it's own output directory so we don't use the same output directory for any of the MFE applications and the hosting application. Except the "remote" MFE application we also disable SSG as we don't need that for any other MFE application. We also enable CORS for each MFE application which will be called by the hosting application as the hosting application will send network requests to these MFE applications from &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; which is a different hostname than the MFE is listening on and would raise a CORS error in the browser.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Keep in mind that this is just an example and not the pattern you should follow for building for production. Simulating such a setup is way beyond the scope of this blogpost.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Preparing the import map for production use
&lt;/h3&gt;

&lt;p&gt;We need to update the import map of the project to use production versions of dependencies when running the applications in production mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;importMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react@0.0.0-experimental-58af67a8f8-20240628?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/jsx-dev-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react@0.0.0-experimental-58af67a8f8-20240628/jsx-dev-runtime?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react-dom@0.0.0-experimental-58af67a8f8-20240628?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react-dom@0.0.0-experimental-58af67a8f8-20240628/client?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server-dom-webpack/client.browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react-server-dom-webpack@0.0.0-experimental-58af67a8f8-20240628/client.browser?dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3001/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3003/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react@0.0.0-experimental-58af67a8f8-20240628&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/jsx-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react@0.0.0-experimental-58af67a8f8-20240628/jsx-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react-dom@0.0.0-experimental-58af67a8f8-20240628&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react-dom@0.0.0-experimental-58af67a8f8-20240628/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server-dom-webpack/client.browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/react-server-dom-webpack@0.0.0-experimental-58af67a8f8-20240628/client.browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/jsx-dev-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react/jsx-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server-dom-webpack/client.browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we detect that &lt;code&gt;NODE_ENV&lt;/code&gt; not equals "production" we will still use the development versions of the required dependencies. But when we use production mode, we need to use production builds of React and related packages too, so we need to remove the &lt;code&gt;?dev&lt;/code&gt; query param from the esm.sh URL of dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Execute the production build
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will build all applications for production and pre-render the content for the root path of the first MFE and include it in the production build.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start the production server
&lt;/h3&gt;

&lt;p&gt;After building, you can start the applications in production mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will serve the statically generated content along with the dynamic content, providing an optimized and pre-rendered user experience.&lt;/p&gt;

&lt;p&gt;By integrating Static Site Generation (SSG) into your micro-frontend architecture, you ensure that key parts of your application, such as the first MFE, are pre-rendered and optimized for performance. The use of the "remote" flag in the &lt;code&gt;react-server.config.mjs&lt;/code&gt; ensures that these components are statically generated during the production build process. This approach not only improves load times but also enhances SEO and provides a better overall user experience by delivering fully rendered content as soon as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expanding Static Site Generation Beyond Micro-Frontends
&lt;/h3&gt;

&lt;p&gt;Incorporating Static Site Generation (SSG) into your micro-frontend architecture significantly enhances performance by pre-rendering key parts of your application. While we focused on enabling SSG for a specific micro-frontend (MFE) in this example, it's important to note that SSG isn't limited to just the micro-frontend applications. You can also apply SSG to specific routes within the hosting application itself. By selectively pre-rendering routes in the hosting application, you can optimize the delivery of content that remains relatively static, improving load times and ensuring that your users receive fully rendered pages immediately upon request. This flexibility allows you to tailor your application’s performance and scalability precisely to the needs of your project, combining the benefits of dynamic rendering where needed with the speed of pre-rendered static content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Islands: loading MFE content using &lt;code&gt;ReactServerComponent&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a id="server-islands"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To demonstrate how you can load content from micro-frontend (MFE) applications in the hosting application using the ReactServerComponent with url and defer props (similar to Astro’s server islands), we’ll set up the architecture so that MFE content is loaded only on the client side, ensuring that it doesn't affect the initial server-side rendering.&lt;/p&gt;

&lt;p&gt;This approach allows you to load micro-frontend content dynamically on the client side, deferring the load until the user interacts with the page or until after the initial server-side render. This method is useful for improving perceived performance and user experience by focusing on essential content first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a new MFE application with Suspense
&lt;/h3&gt;

&lt;p&gt;Let's create another MFE application, but this time let's use Suspense! By using Suspense the MFE application can use a streaming response, providing an initial loading content and then transform the initial MFE content to the content streamed to the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./streaming.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AsyncComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      This is a remote component that is loaded using Suspense. -&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Streaming&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AsyncComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As usual by now, let's run this MFE using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm react-server ./streaming.jsx &lt;span class="nt"&gt;--port&lt;/span&gt; 3004 &lt;span class="nt"&gt;--open&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Extend &lt;code&gt;package.json&lt;/code&gt; scripts
&lt;/h3&gt;

&lt;p&gt;Add a script to the package.json file to start this new streaming MFE application and also update the &lt;code&gt;dev&lt;/code&gt; script to concurrently run the streaming MFE application too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev:streaming"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server ./streaming.jsx --port 3004 --name streaming"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run-p dev:host dev:remote dev:counter dev:form dev:streaming"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build:streaming"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server build ./streaming.jsx --outDir .react-server-streaming --no-export"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start:streaming"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server start --outDir .react-server-streaming --port 3004 --cors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run-p start:host start:remote start:counter start:form start:streaming"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can run the MFE application using Suspense by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm dev:streaming
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add the streaming MFE Application to the Hosting Application
&lt;/h3&gt;

&lt;p&gt;Modify the &lt;code&gt;HostingApplication&lt;/code&gt; to include the new &lt;code&gt;ReactServerComponent&lt;/code&gt; for the streaming MFE:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./index.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RemoteComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lazarv/react-server/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ReactServerComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lazarv/react-server/navigation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HostingApplication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to the Hosting Application&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is a simple React Server Component.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RemoteComponent&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3001"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RemoteComponent&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3002"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RemoteComponent&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3003"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReactServerComponent&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:3004"&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup we keep all of our previous MFE applications rendered using server-side rendering in the hosting application using &lt;code&gt;RemoteComponent&lt;/code&gt; while rendering the streaming MFE only on the client by using the &lt;code&gt;ReactServerComponent&lt;/code&gt;. As soon as the component renders on the client it starts fetching the streaming content from the streaming MFE we just created.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@lazarv/react-server&lt;/code&gt; uses the same &lt;code&gt;ReactServerComponent&lt;/code&gt; for hydrating your app on the client side. Only the behavior of the component differs in this case and that the component will fetch it's content from an external source by specifying the &lt;code&gt;url&lt;/code&gt; prop and that external source in this case is the streaming MFE.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You can extend this by wrapping the &lt;code&gt;ReactServerComponent&lt;/code&gt; into a component using a &lt;code&gt;MutationObserver&lt;/code&gt; to render the &lt;code&gt;ReactServerComponent&lt;/code&gt; only when it's container becomes visible on the page.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now start the hosting application along with the streaming MFE application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using &lt;code&gt;ReactServerComponent&lt;/code&gt; with the &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;defer&lt;/code&gt; props in the hosting application, you can dynamically load and render content from micro-frontends on the client side, similar to Astro's server islands. This approach allows you to optimize your application's performance by prioritizing critical content during the initial server-side render, while still leveraging the power of micro-frontends to deliver additional, modular functionality as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared State Management in a Micro-Frontend Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a id="shared-state-management"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Managing shared state across multiple micro-frontends is one of the more challenging aspects of a micro-frontend architecture. When building modular applications with independent micro-frontends, ensuring consistent and efficient state management becomes critical. In this section, we’ll explore both backend state management and client-side cross-app state management strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend State Management
&lt;/h3&gt;

&lt;p&gt;Backend state management involves centralizing the application's state on the server. This approach ensures that all micro-frontends access a consistent state, regardless of which part of the application is being used. By keeping the state on the server, you reduce the risk of state divergence and improve synchronization across different parts of your application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-Side State with APIs:&lt;/strong&gt; In a typical setup, the server maintains the state and exposes it through RESTful or GraphQL APIs. Each micro-frontend can query the server to fetch the current state and update it as needed. For example, if one micro-frontend updates a user profile, that change is immediately reflected when another micro-frontend queries the user data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Actions for State Management:&lt;/strong&gt; Using server actions, as discussed earlier, is another powerful way to manage state. Server actions allow micro-frontends to interact with server-side logic directly. For instance, you might have a server action that updates a shared counter or user session, ensuring that all parts of your application stay in sync.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Persistence:&lt;/strong&gt; Persisting state on the backend can be handled through databases or in-memory data stores like Redis. These data stores allow you to maintain a global state that can be accessed and modified by any micro-frontend, providing a single source of truth for the application.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Client-Side Cross-App State Management
&lt;/h3&gt;

&lt;p&gt;While backend state management ensures consistency, there are scenarios where sharing state directly on the client side is more efficient, especially for real-time interactions or when minimizing server calls is crucial.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Shared State Libraries:&lt;/strong&gt; Libraries like Redux, Jotai or Zustand can be used to manage client-side state that needs to be shared across multiple micro-frontends. By configuring a shared store, different micro-frontends can read from and write to the same state, ensuring that all components reflect the current state of the application.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;For example, you might have a shared Redux store that holds authentication information, and each micro-frontend can access this store to determine whether a user is logged in and what permissions they have.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Custom Event Systems:&lt;/strong&gt; Implementing a custom event bus is another way to share state across micro-frontends on the client side. This approach involves creating a global event system where micro-frontends can emit and listen for events, allowing them to communicate and synchronize state changes without directly depending on each other.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;For instance, when one micro-frontend updates a cart item, it emits an event that other micro-frontends listen for, allowing them to update the cart UI accordingly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Web Storage:&lt;/strong&gt; Web storage solutions like &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;sessionStorage&lt;/code&gt; or IndexedDB can be used for simpler cross-app state sharing. Micro-frontends can write to and read from these storage mechanisms, ensuring that state persists across page reloads or navigations.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;This approach works well for non-sensitive data that doesn’t need to be immediately synchronized across micro-frontends but still needs to be accessible globally, like user preferences or temporary filters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Combining Backend and Client-Side State Management
&lt;/h3&gt;

&lt;p&gt;In practice, a robust micro-frontend architecture often uses a combination of backend and client-side state management. For critical state that requires consistency across all parts of the application, such as user sessions or permissions, backend state management is essential. However, for performance-sensitive operations or real-time interactions, client-side state management offers flexibility and speed.&lt;/p&gt;

&lt;p&gt;By carefully choosing where and how state is managed, you can ensure that your micro-frontends are both independent and synchronized, providing a seamless user experience across your application. This balance allows for the efficient development and deployment of individual micro-frontends while maintaining the integrity of the overall application state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leveraging Native ES Modules with &lt;code&gt;@lazarv/react-server&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a id="es-modules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The fact that &lt;code&gt;@lazarv/react-server&lt;/code&gt; natively supports ES modules through Vite and Rollup is a significant advantage for developers building micro-frontends. Vite’s use of native ES modules during development allows for faster builds and more efficient hot module replacement, making the development process smoother and more responsive. When it comes time to build for production, Rollup optimizes these ES modules, ensuring that your application is as performant as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Native ES Modules Simplify Micro-Frontend Architecture
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Streamlined Development with Vite:&lt;/strong&gt; Vite’s use of native ES modules means that during development, each micro-frontend can be built and tested independently with minimal configuration. The development server leverages the browser's native support for ES modules, loading dependencies directly as needed. This leads to faster development cycles, as changes are reflected almost instantly without the need for complex bundling steps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimized Production Builds with Rollup:&lt;/strong&gt; Rollup takes the ES module-based development environment created by Vite and produces optimized bundles for production. These bundles are smaller, more efficient, and easier to manage, which is especially important in a micro-frontend architecture where multiple independently developed frontends need to come together seamlessly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplified Dependency Management:&lt;/strong&gt; Since &lt;code&gt;@lazarv/react-server&lt;/code&gt; uses native ES modules, managing dependencies across different micro-frontends becomes much simpler. Each micro-frontend can specify and import only the dependencies it needs without worrying about global conflicts or redundant code. This also enables you to take advantage of tree-shaking, where unused code is automatically removed during the build process, further optimizing your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Modularity and Flexibility:&lt;/strong&gt; With native ES modules, the architecture of your micro-frontends becomes more modular. Each micro-frontend is essentially a self-contained unit that can be developed, tested, and deployed independently. This modularity is enhanced by the fact that Vite and Rollup are designed to work seamlessly with ES modules, allowing for easy integration of new features and components without disrupting the overall application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Faster Builds and Deployments:&lt;/strong&gt; The combination of Vite and Rollup enables quicker build times and more efficient deployments. Vite's instant server start and hot module replacement make development faster, while Rollup's tree-shaking and code-splitting capabilities ensure that the final production bundles are as lean as possible. This is particularly beneficial in a micro-frontend environment, where minimizing build and deployment times is crucial for maintaining agility.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The built-in use of native ES modules in &lt;code&gt;@lazarv/react-server&lt;/code&gt;, facilitated by Vite and Rollup, significantly enhances the development and deployment process for micro-frontends. This approach not only simplifies dependency management and module bundling but also ensures that each micro-frontend can operate independently while still contributing to a cohesive and performant overall application. By leveraging these tools, &lt;code&gt;@lazarv/react-server&lt;/code&gt; offers a streamlined, modular, and efficient architecture that is well-suited to the demands of modern web development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;&lt;a id="final-thoughts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Working with &lt;code&gt;@lazarv/react-server&lt;/code&gt; to build a micro-frontend architecture has been an exciting journey, showcasing the framework's potential to revolutionize how we approach modular web development. This framework offers a unique blend of server-side rendering, dynamic content loading, and modular front-end development, making it a powerful tool for creating scalable and maintainable applications.&lt;/p&gt;

&lt;p&gt;However, it's important to acknowledge that &lt;code&gt;@lazarv/react-server&lt;/code&gt; is still in an experimental phase. While the current capabilities are impressive, there are numerous opportunities for refinement and enhancement. For instance, simplifying the API and improving tooling support could make the framework even more accessible to developers. Additionally, as more developers start using it, we can expect the community to drive innovations that further optimize performance and streamline the development process.&lt;/p&gt;

&lt;p&gt;One of the most exciting aspects of &lt;code&gt;@lazarv/react-server&lt;/code&gt; is its extendability. The architecture is designed to adapt and grow alongside your application’s needs. Whether you’re looking to incorporate advanced caching strategies, integrate with modern deployment pipelines, or explore new rendering techniques, the framework is flexible enough to accommodate these ambitions.&lt;/p&gt;

&lt;p&gt;In summary, while &lt;code&gt;@lazarv/react-server&lt;/code&gt; is a powerful tool with a promising future, it’s also a work in progress. As the framework evolves, it will undoubtedly continue to push the boundaries of what’s possible in web development, offering new ways to build fast, scalable, and maintainable applications. The journey with &lt;code&gt;@lazarv/react-server&lt;/code&gt; is just beginning, and there’s a lot to look forward to as it matures and expands its capabilities.&lt;/p&gt;

</description>
      <category>rsc</category>
      <category>react</category>
      <category>ssr</category>
      <category>microfrontend</category>
    </item>
    <item>
      <title>The Hidden Economy of Technology: How Tech's Most Difficult Tools Fuel an Industry</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Wed, 14 Aug 2024 20:03:37 +0000</pubDate>
      <link>https://forem.com/lazarv/the-hidden-economy-of-technology-how-techs-most-difficult-tools-fuel-an-industry-446m</link>
      <guid>https://forem.com/lazarv/the-hidden-economy-of-technology-how-techs-most-difficult-tools-fuel-an-industry-446m</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the fast-paced world of technology, complexity is often seen as a necessary evil—a byproduct of sophisticated systems designed to solve challenging problems. But what if complexity isn't just an unintended consequence? What if, in some cases, it drives a broader ecosystem that benefits more than just the engineers who master it? From consultants and content creators to corporate strategies and niche specializations, the intricate dance with complexity has created a thriving economy all its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Power of Complexity in Technology
&lt;/h2&gt;

&lt;p&gt;At first glance, complexity in technology might seem like an obstacle—something to be overcome or simplified. But a deeper look reveals that this complexity often fuels an entire industry, creating opportunities for economic gain, educational advancement, and career specialization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtibcxne5micofxpt4jb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtibcxne5micofxpt4jb.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Consultancy Boom: Turning Complexity into Profit
&lt;/h3&gt;

&lt;p&gt;Complex technologies demand expertise. This need has given rise to a robust consultancy market, where businesses and organizations seek out specialists who can navigate these intricate systems. Whether it’s implementing a new enterprise resource planning (ERP) system, optimizing a cloud infrastructure, or managing a complex cybersecurity framework, consultants are in high demand. The more complex the technology, the higher the demand—and the higher the fees.&lt;/p&gt;

&lt;p&gt;Consultants don't just solve problems; they offer peace of mind. Companies are willing to pay a premium for the assurance that their complex systems are in capable hands, making consultancy a lucrative field for those who have mastered the intricacies of these technologies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchoimr2trh8flmvkbmlj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchoimr2trh8flmvkbmlj.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Education and Training: A Growing Industry
&lt;/h3&gt;

&lt;p&gt;The complexity of modern tools and systems has also spurred a booming market in education and training. Companies, universities, and independent platforms like Udemy and Coursera offer specialized courses aimed at demystifying these technologies. Certifications have become badges of honor in the tech world, validating one's ability to navigate and master complex systems.&lt;/p&gt;

&lt;p&gt;For those looking to enter the tech industry or advance their careers, these training programs are invaluable. But they’re also big business. The more difficult the subject, the more willing individuals and companies are to invest in education. This has led to a proliferation of training programs, boot camps, and online courses designed to make complexity more manageable—while also turning a profit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndch6xbxju8kxx5hz93k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndch6xbxju8kxx5hz93k.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Content Creation: Complexity as a Content Goldmine
&lt;/h3&gt;

&lt;p&gt;In the age of digital content, complexity is a goldmine for creators. YouTube channels, blogs, and podcasts that focus on teaching complex technologies attract dedicated audiences eager to learn. These platforms provide tutorials, tips, and deep dives into the nuances of difficult tools, all while generating income through ads, sponsorships, and paid subscriptions.&lt;/p&gt;

&lt;p&gt;For content creators, the appeal is clear: the more complex the subject matter, the more valuable their content becomes. A niche audience of dedicated learners often means higher engagement, more views, and a steady stream of income. Platforms like Patreon have further enabled creators to monetize their expertise, offering exclusive content and one-on-one mentoring for a fee.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21mreubdjpxpasvxej5n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21mreubdjpxpasvxej5n.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Job Market Dynamics: Complexity as a Career Booster
&lt;/h3&gt;

&lt;p&gt;Mastering complex technologies can be a significant career booster. The scarcity of experts in a particular field means that those who do possess the necessary skills are highly sought after. This demand often translates into higher salaries, better job security, and more opportunities for advancement.&lt;/p&gt;

&lt;p&gt;In some cases, entire careers are built around niche specializations in complex technologies. These specialists become indispensable within their organizations, offering expertise that few others possess. The more intricate the technology, the more valuable the specialist, creating a virtuous cycle where complexity drives career growth.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6u1pbbb1izq01mi704f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6u1pbbb1izq01mi704f.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Corporate Strategy: Leveraging Complexity for Competitive Advantage
&lt;/h3&gt;

&lt;p&gt;Corporations are not blind to the power of complexity. In some cases, companies might intentionally design their systems or technologies to be complex as a form of competitive advantage. This can lead to vendor lock-in, where the difficulty of switching to a different system ensures long-term contracts and ongoing revenue streams.&lt;/p&gt;

&lt;p&gt;Furthermore, the development of complex systems often results in the creation of intellectual property (IP) and patents. These assets can give companies a significant edge in the market, creating barriers to entry for competitors and establishing the company as a leader in a particular technology.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fulsz6jyud41o7ovbgmli.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fulsz6jyud41o7ovbgmli.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. The Perpetuation of Complexity: A Self-Sustaining Cycle
&lt;/h3&gt;

&lt;p&gt;Over time, complex technologies often become entrenched as legacy systems, further perpetuating their complexity. As these systems evolve, they accumulate additional layers of features and requirements, making them even more difficult to master. This perpetuation creates a continuous need for education, training, and consultancy, sustaining the ecosystem that has grown around the technology.&lt;/p&gt;

&lt;p&gt;Ironically, the complexity itself can drive demand for tools and services that simplify or abstract away that complexity. This has led to the rise of frameworks, platforms, and services that aim to make complex technologies more accessible—yet often become complex themselves as they grow.&lt;/p&gt;

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

&lt;p&gt;Complexity in technology is not just a challenge to be overcome; it’s a driver of economic opportunity and industry growth. From consultancy and education to content creation and corporate strategy, the intricate nature of modern tools fuels a multi-faceted ecosystem that benefits a wide range of stakeholders. While this complexity may frustrate users, it also creates a thriving market for those who are willing to embrace it.&lt;/p&gt;

&lt;p&gt;In the end, the relationship between complexity and opportunity is symbiotic. As technology continues to advance, this hidden economy of complexity is likely to grow, offering new avenues for innovation, specialization, and economic gain. Whether you’re a consultant, a content creator, or a tech professional, understanding and navigating this complexity can be your key to success in the ever-evolving world of technology.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: This blog post was generated with the assistance of ChatGPT, an AI language model developed by OpenAI. This post is part of a test to gauge viewership and engagement. The content reflects a combination of AI-generated ideas and human curation. We appreciate your feedback and interest in this experiment!&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Migrating a Vite + React app to use React Server Components</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Sun, 11 Aug 2024 12:25:11 +0000</pubDate>
      <link>https://forem.com/lazarv/migrating-a-vite-react-app-to-use-react-server-components-507j</link>
      <guid>https://forem.com/lazarv/migrating-a-vite-react-app-to-use-react-server-components-507j</guid>
      <description>&lt;p&gt;Vite has the best developer experience a web developer could wish for. When you want to create a single page application using React then Vite is your default choice. It's incomparable how much better it is than using &lt;code&gt;create-react-app&lt;/code&gt; just a few years ago. Who really misses Webpack? Who misses complex configurations?&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Starting a new Vite + React app is easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm create vite my-react-app &lt;span class="nt"&gt;--template&lt;/span&gt; react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you just need to change directory, install dependencies and start your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-react-app
pnpm &lt;span class="nb"&gt;install
&lt;/span&gt;pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It just works!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxvg71davn5rx7t4fk55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxvg71davn5rx7t4fk55.png" alt="Image description" width="800" height="831"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can achieve great things working only on the client side, what Kent C. Dodds is presenting in this great video is awesome and perfectly viable in a lot of use cases:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/rPjj6s7VPQM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;But is it really enough? Probably it is most of the time, but everyone wants server-side rendering nowadays, the hype is real and we want it too, so let's continue...&lt;/p&gt;

&lt;h2&gt;
  
  
  React Server Components
&lt;/h2&gt;

&lt;p&gt;The hype around RSCs are still rising! More and more frameworks are starting to support the new server-side rendering features of the upcoming new major release of React.&lt;/p&gt;

&lt;p&gt;Surely Next.js was the first to jump on the train (they built it for themselves) and Vercel started to teach developers around the world about the benefits of using RSCs, including how to work with client components and server actions too.&lt;/p&gt;

&lt;p&gt;Other major React based frameworks are picking up RSCs a bit slower though. Remix just demonstrated using RSCs in the loader, while not missing working client components:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ZcwA0xt8FlQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Astro is more likely a bit off here as while it supports React, it's implementing it's own similar solutions, like Astro Actions:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/VkYQMhit_04"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;RedwoodJS also works on RSC support and Waku supports the new features already.&lt;/p&gt;

&lt;p&gt;You can also start building your own framework from scratch or using vinxi. But how many developers are up to do this? It's not even really documented how to do it! What about web developers who are not experienced enough or don't have the time to go down this road? Surely there are some, like Hiroshi implementing an RSC supprting framework using both the current Vite API at &lt;a href="https://github.com/hi-ogawa/vite-plugins/tree/main/packages/react-server" rel="noopener noreferrer"&gt;https://github.com/hi-ogawa/vite-plugins/tree/main/packages/react-server&lt;/a&gt; and using the incoming Vite 6 Environment API at &lt;a href="https://github.com/hi-ogawa/vite-environment-examples/tree/main/examples/react-server" rel="noopener noreferrer"&gt;https://github.com/hi-ogawa/vite-environment-examples/tree/main/examples/react-server&lt;/a&gt;. Also there's a great article from Daniel Nagy about building your own framework using Vite and RSC support at &lt;a href="https://danielnagy.me/posts/Post_usaivhdu3j5d" rel="noopener noreferrer"&gt;https://danielnagy.me/posts/Post_usaivhdu3j5d&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But we are drifting too far away from the original simplicity and easy start we had. How to enhance your simple Vite + React single page application with modern server-side rendering?&lt;/p&gt;

&lt;p&gt;A bit controversial tutorial you can find is from Vercel, presented by Lee Robinson:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/AdkNcFUsRQQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;But surely a lot of us were very disappointed when the starting Vite client-side app became a heavy Next.js app, removing all traces of Vite in the end. But we adore Vite here right? We love how simple it is, how fast it is, how easy it is to extend it using plugins, especially compared to custom Webpack plugins.&lt;/p&gt;

&lt;p&gt;Almost all other frameworks are using Vite now, especially non-React frameworks, like SvelteKit. When you stick with React, Remix is closest to what we wish for and it will be even more when there will be proper RSC support in Remix. You can already use Remix with Vite and it's great! But it's not supporting RSCs yet and you will get some magic files which will be mostly just deleted as it's not likely you want to modify these. Maybe in a couple months, but expect refactoring!&lt;/p&gt;

&lt;p&gt;Is there another choice? A new alternative? Which framework to choose when you want to modify the starting Vite + React app the least and be able to use everything new from React 19?&lt;/p&gt;

&lt;h2&gt;
  
  
  Vite Forever
&lt;/h2&gt;

&lt;p&gt;So let's correct what Lee did and don't go into the wrong direction by migrating over to Next.js and Webpack, let's stick with Vite at least for a few years, maybe even a decade (or more)!&lt;/p&gt;

&lt;p&gt;As we want to use RSCs, let's move everything from the &lt;code&gt;index.html&lt;/code&gt; into &lt;code&gt;src/main.jsx&lt;/code&gt; and instead of rendering &lt;code&gt;App&lt;/code&gt; on the client-side, just use it as a component in this RSC layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.jsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charSet&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"image/svg+xml"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/vite.svg"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Vite + React&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beware that you need to fix &lt;code&gt;charSet&lt;/code&gt; as it has a different casing when used in JSX than in HTML!&lt;/p&gt;

&lt;p&gt;For now, just add a &lt;code&gt;"use client";&lt;/code&gt; directive to &lt;code&gt;App.jsx&lt;/code&gt; to make it work instantly as the App component includes a &lt;code&gt;useState&lt;/code&gt; React hook.&lt;/p&gt;

&lt;p&gt;Now let's uninstall &lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt; as we will not need them, both were just React 18. Now what? How we will run our app?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add @lazarv/react-server@latest 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, I'm installing my own React meta-framework to solve the problem I have here. Is it a better choice than Remix? If you want to use the latest React features, then yes. As it supports RSCs, client components and server actions already, while using Vite, ES modules and keeping everything stupid simple. It's probably best for quick prototyping and for indie devs loving to work with bleeding edge experimental tech. The fact that it was already good enough to implement its own documentation site, using its static-site generation capability, shows great potential. With time, it will become even better and more mature, offering an even wider feature set to work with. You can read more about the framework at &lt;a href="https://react-server.dev" rel="noopener noreferrer"&gt;https://react-server.dev&lt;/a&gt;. Get back to our app now!&lt;/p&gt;

&lt;p&gt;Just make some more changes on how to start our app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server ./src/main.jsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server build ./src/main.jsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint ."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-server start"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you think this is very familiar to how you would use Node.js to run a script, you're right! &lt;code&gt;react-server ./src/main.tsx&lt;/code&gt; is the same as executing &lt;code&gt;node server.js&lt;/code&gt;, just for React RSCs. If it would be enough, we could just run a single RSC component using &lt;code&gt;npx&lt;/code&gt; with this framework, even without installing anything! Just like with Node.js!&lt;/p&gt;

&lt;p&gt;Let's start our app using &lt;code&gt;pnpm dev --open&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5ghtviusmyckghjimxz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5ghtviusmyckghjimxz.png" alt="Image description" width="800" height="733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It just works! Awesome! But can we fix the loading glitch that we can see on refreshing the page? What causes this?&lt;/p&gt;

&lt;h1&gt;
  
  
  Optimizing client components
&lt;/h1&gt;

&lt;p&gt;In the current state of our app, the whole &lt;code&gt;App&lt;/code&gt; component is a client component. This is not ideal, as only the counter part is interactive in it. We also attached some CSS to this client component which will only be loaded when the client component loads in the browser at runtime. This is causing a glitch for a blink of an eye at page load.&lt;/p&gt;

&lt;p&gt;Let's create a new &lt;code&gt;Counter&lt;/code&gt; component in a new file at &lt;code&gt;src/Counter.jsx&lt;/code&gt; and move the counter button into this new component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      count is &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's get back to the &lt;code&gt;App&lt;/code&gt; component, remove the &lt;code&gt;"use client";&lt;/code&gt; directive, remove the &lt;code&gt;App.css&lt;/code&gt; import and the code which was only part of the &lt;code&gt;Counter&lt;/code&gt; component, but import it instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;reactLogo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./assets/react.svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;viteLogo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/vite.svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Counter.jsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://vitejs.dev"&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viteLogo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Vite logo"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://react.dev"&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;reactLogo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"logo react"&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"React logo"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Vite + React&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Edit &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;src/App.jsx&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; and save to test HMR
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"read-the-docs"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Click on the Vite and React logos to learn more
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The easiest resolution of the CSS issue is to import &lt;code&gt;App.css&lt;/code&gt; in  &lt;code&gt;main.jsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.jsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// we don't need to do any change here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now both CSS files will be loaded instantly on page load and there will be no flickering. The counter button will still work as before as we refactored it to be a new client component. Every other part of the &lt;code&gt;App&lt;/code&gt; component was static, which is best to be included in RSCs. You can also combine the 2 CSS files as there's no reason why we have two, just fix the CSS imports in the &lt;code&gt;main.jsx&lt;/code&gt; after that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go?
&lt;/h2&gt;

&lt;p&gt;Now we have the same Vite + React app working with server-side rendering. But how to evolve from this state further?&lt;/p&gt;

&lt;p&gt;You can start implementing a form using server actions, just as described at &lt;a href="https://react.dev/reference/rsc/server-actions" rel="noopener noreferrer"&gt;https://react.dev/reference/rsc/server-actions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can add a router, maybe a file-system based routing solution supporting RSCs, like &lt;code&gt;@lazarv/react-server-router&lt;/code&gt;. It's very flexible!&lt;/p&gt;

&lt;p&gt;You can export your app as static as there might be no reason to use dynamic server-side rendering and it's enough for you to render your app at build time.&lt;/p&gt;

&lt;p&gt;You can add any Vite plugin and remain in this wonderful ecosystem, extending your app at any time.&lt;/p&gt;

&lt;p&gt;You can eagerly wait for a version of Vite using Rolldown, to have an even more blazing-fast developer experience!&lt;/p&gt;

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

&lt;p&gt;While RSCs are with us for quite some time now, we are still learning how to use them properly. It's a super-power to have and it will certainly evolve further. But it's more like a beast to tame than an easy to understand feature. We are holding endless possibilities in our hands, but most of us don't know what to do with it. With great power comes great responsibility! But even when we tend to over-engineer even extremely simple problems, we like to work with simple technologies. That's how Vite won and how PHP is still with us. It's easy to use. A lot of us are not god-like developers implementing anything from scratch in a day. We are just mere humans trying hard to make some silly things work. And we fail a lot. But we win in the end with persistence, like long-distance runners.&lt;/p&gt;

&lt;p&gt;We should stick to what we already learned in the past. We should not forget, that we already knew how to make things efficiently. We had worse tools, worse tech, worse machines, but it was possible because of creativity and endurance to create wonderful things. Now we should use our new tools, new tech, new machines and we should still use our creativity and imagination to create even more fascinating experiences. We are responsible for making people happy to use our products. Even as software engineers.&lt;/p&gt;

</description>
      <category>vite</category>
      <category>react</category>
      <category>rsc</category>
    </item>
    <item>
      <title>@lazarv/react-server vs Next.js</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Sun, 07 Jul 2024 17:12:26 +0000</pubDate>
      <link>https://forem.com/lazarv/lazarvreact-server-vs-nextjs-ok8</link>
      <guid>https://forem.com/lazarv/lazarvreact-server-vs-nextjs-ok8</guid>
      <description>&lt;p&gt;In this article we will compare &lt;a href="https://react-server.dev" rel="noopener noreferrer"&gt;@lazarv/react-server&lt;/a&gt; to Next.js as these React meta-frameworks are very close because both are based on the new React 19 server-side rendering features.&lt;/p&gt;

&lt;p&gt;We will investigate both frameworks on their approach and architectural choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a meta-framework?
&lt;/h2&gt;

&lt;p&gt;We can consider a solution to be a meta-framework when the following features are supported and the framework is using a specific library as it's base. Which is React in our case.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File-based routing&lt;/li&gt;
&lt;li&gt;Static generation&lt;/li&gt;
&lt;li&gt;Hybrid rendering&lt;/li&gt;
&lt;li&gt;Data fetching&lt;/li&gt;
&lt;li&gt;Isomorphic component trees&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The React team suggests to use a framework for future React development. Next.js, Remix, Gatsby and Expo are their suggestion, while mentioning Next.js App Router as the bleeding-edge framework. If you really want to use React without a framework, you can still use a bundler like Vite or Parcel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js
&lt;/h2&gt;

&lt;p&gt;Originally released in 2016 and nowadays it's the go-to meta-framework for React. There are some developers from the Next.js team who are also involved in the development of React itself. This means that Next.js is following the architectural choices the React team considers the best for React. This could be true for certain use cases, but still it's debatable. One major issue with Next.js is that  it's optimized for the Vercel platform in every single way. While you can run your Next.js app in every environment which supports node.js, making this choice removes or at least diminishes a lot of nice and valuable features from your Next.js app, which could use Vercel platform features to implement these app features in the most optimal way. You can think of image optimalization, ISR, caching, etc.&lt;/p&gt;

&lt;p&gt;Next.js is using Webpack under the hood to bundle your app. While there's experimental support for Turbopack and support for using SWC and Lightning CSS as the compiler. Next.js is still using CommonJS (with some support for ES modules), while the node.js community is mostly trying to switch over to native ES modules and CommonJS is considered legacy now, with some exceptions. Support will remain for years for sure, but there are already npm packages which only support ES modules since a specific version.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://react-server.dev" rel="noopener noreferrer"&gt;@lazarv/react-server&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In contrast to Next.js, &lt;code&gt;@lazarv/react-server&lt;/code&gt; is using Vite for it's development server and as using Vite, it's bundling for production using Rollup. With this choice it's fully supporting native ES modules. This framework is not favoring any cloud providers like Vercel, but supports deployment to Vercel. As the framework is more of a wrapper around React 19 server-side rendering features without any strict choices on how to implement specific features, it's easier to shape your app the way you want it to work and behave. The only exception is that it will use Vite. Based on that, it's also easier to run apps literally anywhere where you can run a node.js service. The framework also supports cluster mode, which creates a node.js cluster for your app which is beneficial if you run your app in an environment where you want to fully utilize the available resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared features
&lt;/h2&gt;

&lt;p&gt;As both &lt;code&gt;@lazarv/react-server&lt;/code&gt; and Next.js is using React at it's core, both share a lot of features which are provided by React and are not Next.js nor &lt;code&gt;@lazarv/react-server&lt;/code&gt; features directly.&lt;/p&gt;

&lt;p&gt;React Server Components is a hot topic in the community and it's a very versatile tool. It's surely is the next most different new feature in React 19 since hooks. RSCs are rendered only on the server-side and have no client code so you can't re-render these on the client.&lt;/p&gt;

&lt;p&gt;To open a door from RSCs into the client code, you need to create client components. This type of components are basically the same as you already used to in a React server-side rendered app. These are also rendered on the server, but getting hydrated on the client and these are able to re-render on the client based on their state. You can mix RSCs and client components in every way. RSCs can contain client components and client components can also contain RSCs. It's absolutely up to the developer how the app is structured and which part of the app is using RSCs and which part is created using client components and are also running in the browser.&lt;/p&gt;

&lt;p&gt;Using RSCs you are able to load initial data into your client components. To use mutation, you can use server actions. This feature is like a built-in RPC into React and the React meta-frameworks. You can call a server action using HTML form or button elements or by passing the server action as a reference to the client component and calling it like a normal async JavaScript function.&lt;/p&gt;

&lt;p&gt;While with Next.js you have to use it's built-in file-based router named the App Router, when you're using &lt;code&gt;@lazarv/react-server&lt;/code&gt; it's only up to you if you want to use the optional file-based router or you want to implement your application using another solution. If you still need the file-based router, both framework's solution for the router is very similar and if you used Next.js App Router, it will be easy to do the same using &lt;code&gt;@lazarv/react-server-router&lt;/code&gt;. It's just optional. Both framework's routing solution supports middlewares and API routes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;All frameworks provide a project creation command line tool for developers to help getting started with it. Next.js has &lt;code&gt;npx create-next-app&lt;/code&gt;, Remix has &lt;code&gt;npx create-remix&lt;/code&gt;, etc. All of these CLI tools create a new project, initializing files required to run your app using that framework and it's also installing required dependencies. These are mostly marketed as a 5min task. Which is fair. These tools are easy to use and it's really just a few minutes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@lazarv/react-server&lt;/code&gt; is different. You don't need any tools to initialize your app. You just need &lt;code&gt;@lazarv/react-server&lt;/code&gt;. After installing it as a dependency or just using &lt;code&gt;npx&lt;/code&gt; to run the framework's CLI, you're done. It brings back the most simple developer experience ever: &lt;code&gt;node server.js&lt;/code&gt;. You already have a JSX file with a component? Just run &lt;code&gt;npx @lazarv/react-server ./App.jsx&lt;/code&gt;. You don't need to install React. It would be pointless and Next.js is also including it's own specific version of React as for all React 19 and experimental React features to work properly, you need a specific version of React. &lt;code&gt;@lazarv/react-server&lt;/code&gt; installs it's own React too. So running your first app with &lt;code&gt;@lazarv/react-server&lt;/code&gt; takes a few seconds. Nothing more. But infinitely expandable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some numbers
&lt;/h2&gt;

&lt;p&gt;Next.js can be slow. This might not feels that much until you experienced something better and &lt;code&gt;@lazarv/react-server&lt;/code&gt; wins by a lot in this. You can experience the same when you migrated your old Create React App project to Vite.&lt;/p&gt;

&lt;p&gt;Our benchmark app might feel weak as it's only the most simple React app possible, but measuring the difference even in this most minimal use case means that Next.js will always lag behind because it's heavy-weight architecture. This is not achieved by using a faster bundler, only with a more suiting architecture.&lt;/p&gt;

&lt;p&gt;Our tiny app looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Next.js a mock layout file also needs to be created, just rendering &lt;code&gt;children&lt;/code&gt; and doing nothing else.&lt;/p&gt;

&lt;p&gt;The results seem devastating:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Next.js&lt;/th&gt;
&lt;th&gt;&lt;code&gt;@lazarv/react-server&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;startup&lt;/td&gt;
&lt;td&gt;~800ms&lt;/td&gt;
&lt;td&gt;~150ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;compiling&lt;/td&gt;
&lt;td&gt;~600ms&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;page load&lt;/td&gt;
&lt;td&gt;~150ms&lt;/td&gt;
&lt;td&gt;~30ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;build&lt;/td&gt;
&lt;td&gt;~3.5s&lt;/td&gt;
&lt;td&gt;~200ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;start&lt;/td&gt;
&lt;td&gt;~100ms&lt;/td&gt;
&lt;td&gt;~100ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rps&lt;/td&gt;
&lt;td&gt;~9k&lt;/td&gt;
&lt;td&gt;~21k&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Using the cluster mode available for the production runtime of &lt;code&gt;@lazarv/react-server&lt;/code&gt; you can achieve even more blazing-fast performance even without caching. Using an 8 core M3 Macbook Air it's hitting a whopping ~50k requests per second using all the available CPU cores, so running 8 workers!&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Let's get a look on each type of result and the reason behind the numbers!&lt;/p&gt;

&lt;h4&gt;
  
  
  startup
&lt;/h4&gt;

&lt;p&gt;This is the startup time for the development server. Next.js startup is more than 4x. Next.js is much more heavy and core codebase of Next.js is way too much for an app like this, while &lt;code&gt;@lazarv/react-server&lt;/code&gt; is a light-weight server with being a wrapper around Vite and React where no unnecessary code is run on startup.&lt;/p&gt;

&lt;h4&gt;
  
  
  compiling
&lt;/h4&gt;

&lt;p&gt;Next.js needs to create a bundle for your app. But using Vite, &lt;code&gt;@lazarv/react-server&lt;/code&gt; eliminates this part by not creating any bundle during development. The underlying bundler in case of Vite doesn't need to collect and compile a bundle before you could use your app. This is an essential architectural choice with Vite. Learn more about this at &lt;a href="https://vitejs.dev/guide/why.html" rel="noopener noreferrer"&gt;Why Vite?&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  page load
&lt;/h4&gt;

&lt;p&gt;Next.js loads roughly twice as much client side code when running your app and the client-side router is much more complex. Performance for page load is about 5x with &lt;code&gt;@lazarv/react-server&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  build
&lt;/h4&gt;

&lt;p&gt;When you are finished implementing your app and ready to deploy it to somewhere, you need to build your app for production use. Again, Next.js is lagging behind. Even when using a powerhouse developer machine, it takes seconds to build your Next.js app for production! While the Rollup based build in &lt;code&gt;@lazarv/react-server&lt;/code&gt; is just a blink of an eye compared to the Next.js build. The difference is most prominent in this case between the two frameworks. &lt;code&gt;@lazarv/react-server&lt;/code&gt; wins by a whopping 18x performance gain!&lt;/p&gt;

&lt;h4&gt;
  
  
  start
&lt;/h4&gt;

&lt;p&gt;This is the startup time for the production server of the framework and also the only category which the frameworks are getting a tie.&lt;/p&gt;

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

&lt;p&gt;Do you really need to work with Next.js all the time and in all use case? Surely not. Next.js might be still excellent and awesome for a ton of apps. But there are also way to many apps that are using Next.js even when they should not. By using &lt;code&gt;@lazarv/react-server&lt;/code&gt; developers don't need to use a heavier framework like Next.js when the app is not needing all features or you will run your app on your own. When you would use Vite for a single page application, but might be a bit jealous on the SSR niceties React 19 provides.&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>ssr</category>
    </item>
    <item>
      <title>My story creating a new React meta-framework</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Mon, 10 Jun 2024 22:20:51 +0000</pubDate>
      <link>https://forem.com/lazarv/my-story-creating-a-new-react-meta-framework-732</link>
      <guid>https://forem.com/lazarv/my-story-creating-a-new-react-meta-framework-732</guid>
      <description>&lt;p&gt;I have a great idea for a new hobby project! As I am a React developer, I'll use it again for implementing this project, that's an easy choice. I use Next.js at work. It's fine, but there are some pain points in using it, so I don't want to go with it for my own project. I struggle with it during work, so why should I struggle in my spare time. I want to have some fun!&lt;/p&gt;

&lt;p&gt;I love Vite! When I used Vite for a React SPA app, with React Router and react-query, I liked it a lot! It was blazing-fast! No need to wait for any Webpack bundling, just using ES modules, it was heavenly. I started to use Vite when I started experimenting with streaming server-side rendering using React Suspense. I also created a micro-frontend system based on Vite and a self-hosted fork of esm.sh instead of Module Federation, but that's another story.&lt;/p&gt;

&lt;p&gt;But this Vite setup I had for an SPA didn't work for server-side rendering as I wanted it to. Should I use Remix then? Remix now supports Vite! Though choice. I like some parts of Next.js since Next.js 13. More precisely, I like the new React server-side rendering features a lot. React Server Components are awesome! To have complete control over the React hydration and which parts of the rendering is server vs client is great. Using server actions with Next.js is also fantastic! I like how much this new way is close to traditional web development. I like that links and forms are driving navigation, mutation and that state management is shared between the client and the server using standard solutions, like search params and RESTish routing, even some cookies if needed. Web development is again so much easier and fun this way. But I don't want to have all the caching problems of Next.js. I don't want bundles and waiting. So what should I use again? Remix is not supporting these. What about Astro? I like Astro, I would possibly use it for a more content driven project, but this time, it's not my best choice. I only want to use pure React. I heard there's a new minimal React framework, Waku. I want to have even less setup than that!&lt;/p&gt;

&lt;p&gt;To summarize, what will I need or want to use for this project?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vite&lt;/li&gt;
&lt;li&gt;server-side rendering&lt;/li&gt;
&lt;li&gt;React Server Components&lt;/li&gt;
&lt;li&gt;client components&lt;/li&gt;
&lt;li&gt;server actions&lt;/li&gt;
&lt;li&gt;full access to the HTTP context&lt;/li&gt;
&lt;li&gt;a minimal setup, no boilerplate&lt;/li&gt;
&lt;li&gt;fast dev server, build and deploy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is there a framework like that? No. I worked on some libraries and frameworks in the past, like JayData or odata-v4-server, so if I would create a new React framework with the requirements I have, how should it be done? That's a though question as there's no documentation for these React features yet, just some tests in the React repo and while Next.js is open source, the codebase is huge! I love to experiment with un-documented tech, I loved when I learned the intricacies of the unknown and then tweaking it to the max to create an awesome, jaw-dropping experience, like porting Wolfenstein 3D to the web from scratch, directly porting some C/C++ code to JavaScript while learning a lot or using WebAssembly to create a DOOM web runtime environment to play any WAD files from DOOM I or II, even other DOOM-engine games like Heretic. I loved re-engineering these retro games to make them playable in the browser or on my phone or tablet. I also started to make a dive and started messing around with the Elder Scrolls series to remake it in the browser! It was so much fun! So, without any hesitance, I started to create some proof of concepts.&lt;/p&gt;

&lt;p&gt;RSC is easy. You just need to call &lt;code&gt;renderToReadableStream&lt;/code&gt; and send it to the browser. But what about hydration and client components? Now that's a challenge! You need to render your React tree to the RSC payload in a thread with "react-server" module resolution conditions. This payload will include all the static HTML nodes and references to client components and server actions. To render client components properly, you need to have a snapshot. That's the RSC payload, with the static HTML nodes. Then, you need to get a new React tree from this. To get that, you need to use &lt;code&gt;createFromReadbaleStream&lt;/code&gt; to transform your RSC stream to a React tree, then use a different type of &lt;code&gt;renderToReadableStream&lt;/code&gt;, but this time not using the &lt;em&gt;react-server-dom-webpack&lt;/em&gt; package, but &lt;em&gt;react-dom&lt;/em&gt;. While doing this, you need to send your RSC payload in parallel with the HTML content to hydrate your React application on the client as you stream the server-side rendered content. You also need to have all the references ready to tag client components with the &lt;code&gt;react.client.reference&lt;/code&gt; symbol and if you also want server actions, then with the &lt;code&gt;react.server.reference&lt;/code&gt; symbol. So you need to transform your files differently for multiple environments during rendering and you also need to manage all the module resolution for these. Take this with all the workarounds you need to do to make this work with Vite. So after creating some Vite transform plugins and dealing with the complex rendering (not just a simple &lt;code&gt;renderToString&lt;/code&gt; like in the old days), you're good to go, right?&lt;/p&gt;

&lt;p&gt;A framework is much more, than making some proof of concept work. It's much more, than achieving something in a sandbox. It's very similar to game development or it's very similar to me, to my own game development experience as I always worked on some rendering engine for games and not as a game designer or creating content for a new game (with some tiny exceptions). After you finish with the gameplay, you need to start building all the other parts, like menus, configuration management, etc. A framework is not just a rendering engine and some core functionality. It has to provide some great developer experience. I had this partially because of Vite. If I would not have Vite, my job would have been much harder. But I had an idea. A vision.&lt;/p&gt;

&lt;p&gt;When I experienced node.js the first time, I was amazed. I already worked as a frontend engineer, so node.js for me was a gate to another world, to another dimension. I was able to use all my expertise with JavaScript on the backend. I worked a little bit at this point with other backend solutions, like PHP or ASP.NET. But despite it's quirks, I loved JavaScript (I know, I know...). So node.js was the best thing to continue with. What made node.js awesome? &lt;code&gt;node server.js&lt;/code&gt;. If you had a JavaScript file with any size, be it a tiny script or a large backend for a complex architecture, in the end it's just running a simple &lt;code&gt;node&lt;/code&gt; command to start your server.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;react-server ./App.jsx&lt;/code&gt;. I wanted to have this. So badly! All the frameworks are handling your entrypoint differently. Next.js is enforcing it's own file-based routing. It's so much more opinionated compared to React. Remix has a long setup to follow. I just wanted an &lt;code&gt;App.jsx&lt;/code&gt; and a CLI tool to run it as my entrypoint, taking away all the project setup work that every project needs at the start.&lt;/p&gt;

&lt;p&gt;I imagined this "Get started" (I also love &lt;em&gt;pnpm&lt;/em&gt; btw):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm add @lazarv/react-server
pnpm exec react-server ./App.jsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No need for anything else. Simple as that. Not even a configuration file. Not even installing React directly! Just running the Vite development server, like I would do it for an SPA using &lt;code&gt;npx vite&lt;/code&gt; with an &lt;code&gt;index.html&lt;/code&gt; in place. I was amazed by a Vite demo Evan You did more than 2 years ago. It was minimal. It was elegant. It was awesome! I wanted to have the simplicity of node.js and Vite, just for React.&lt;/p&gt;

&lt;p&gt;I also have to mention a very important presentation. It changed how I look on RSCs and the new way of React server-side rendering. It was Dan Abramov’s RemixConf 2023 presentation titled: “React from Another Dimension”. If you haven’t watched it yet, do it. RSC clicked for me watching it! Also the title was great as I listen to Liquid Tension Experiment a lot! :) &lt;/p&gt;

&lt;p&gt;My hobby project grew out of it’s cooking pot. Maybe it’s some sort of megalomania. But I always lose some scope as I dream big. In all my works, I have a much larger target in the end than at the start of that project. But if I’m committed to that project, I will finish and achieve my vision no matter what.&lt;/p&gt;

&lt;p&gt;If you share the same view on frameworks like me, you can get my experience. Just head over to &lt;a href="https://github.com/lazarv/react-server" rel="noopener noreferrer"&gt;https://github.com/lazarv/react-server&lt;/a&gt; and give as much feedback as possible. I also sort of completed my hobby project. But not the original one. I used my own framework to create the documentation site for it. Check it out at &lt;a href="https://react-server.dev" rel="noopener noreferrer"&gt;https://react-server.dev&lt;/a&gt;. I hope you will also have fun trying it out!&lt;/p&gt;

</description>
      <category>react</category>
      <category>vite</category>
      <category>rsc</category>
    </item>
    <item>
      <title>Todo app with no client-side JavaScript using @lazarv/react-server</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Mon, 27 May 2024 17:02:41 +0000</pubDate>
      <link>https://forem.com/lazarv/todo-app-with-no-client-side-javascript-using-lazarvreact-server-23ig</link>
      <guid>https://forem.com/lazarv/todo-app-with-no-client-side-javascript-using-lazarvreact-server-23ig</guid>
      <description>&lt;p&gt;Everyone starts with a simple Todo app when evaluating a new framework. So let’s do it this time using &lt;a href="https://react-server.dev" rel="noopener noreferrer"&gt;@lazarv/react-server&lt;/a&gt;, a new minimalist React meta-framework using Vite!&lt;/p&gt;

&lt;p&gt;Our goal with this example is to use no client-side JavaScript and no React hydration. We only want to use React Server Components and Server Actions. Is this possible? Absolutely!&lt;/p&gt;

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

&lt;p&gt;Let’s create a new project, by creating a new folder, initializing pnpm and installing all the required dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;todo
&lt;span class="nb"&gt;cd &lt;/span&gt;todo
pnpm init
pnpm config &lt;span class="nb"&gt;set &lt;/span&gt;auto-install-peers &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--location&lt;/span&gt; project
pnpm add @lazarv/react-server better-sqlite3 zod
pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; @types/better-sqlite3 @types/react @types/react-dom autoprefixer postcss tailwindcss typescript
pnpx tailwindcss init &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To store our Todo items, we will use a local Sqlite database. For validation, we will use Zod and for styling we will use Tailwind CSS. To include all our source code as Tailwind content, change the &lt;strong&gt;tailwind.config.js&lt;/strong&gt; to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {import('tailwindcss').Config} */&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/**/*.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we will not do any exciting Tailwind styling, put the usual 3-liner Tailwind setup into &lt;strong&gt;src/index.css&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hello World!
&lt;/h2&gt;

&lt;p&gt;Well it’s nothing better than a good old “Hello World!” app, so let’s create an entrypoint for our Todo app! Put the following code into &lt;strong&gt;src/index.tsx&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run this micro-app, you can just use &lt;code&gt;pnpm exec react-server ./src/index.tsx&lt;/code&gt; . To make our life easier, let’s add some npm scripts to &lt;strong&gt;package.json&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server ./src/index.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server build ./src/index.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing this, use &lt;code&gt;pnpm dev&lt;/code&gt; to start the development server. After our development server is running, open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; and be proud of our Hello World! app. You can also use &lt;code&gt;pnpm dev --open&lt;/code&gt; to do so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layout
&lt;/h2&gt;

&lt;p&gt;Our Todo app needs a layout, so let’s create &lt;strong&gt;src/Layout.tsx&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charSet&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Todo&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-4xl font-bold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Todo&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing fancy here, just a usual HTML document template. We will use this Layout component as a wrapper for our app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Page
&lt;/h2&gt;

&lt;p&gt;Our main page will be the Todo app, where we will use all of the building blocks to create our app. Let’s say goodbye to Hello World! and change the component to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;allTodos&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./actions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AddTodo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./AddTodo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Layout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;allTodos&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AddTodo&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-gray-500"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;No todos yet!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this React Server Component, we collect all the stored Todo items by calling &lt;code&gt;allTodos()&lt;/code&gt; and use the result to render JSX. We use the Layout component to wrap our content into a HTML document.&lt;/p&gt;

&lt;h2&gt;
  
  
  Item
&lt;/h2&gt;

&lt;p&gt;To render our items, let’s create an Item component in &lt;strong&gt;src/Item.tsx&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;deleteTodo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./actions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex row items-center justify-between py-1 px-4 my-1 rounded-lg text-lg border bg-gray-100 text-gray-600 mb-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex-1"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;deleteTodo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"font-medium"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Item component will render our Todo item using an &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt; prop. But what about that &lt;code&gt;&amp;lt;form action={deleteTodo}&amp;gt;&lt;/code&gt;? It’s a server action! When the user will submit the form by clicking on the “Delete” button, the browser will call our server action. This is possible without any JavaScript on the frontend, as React supports progressive enhancement for server actions and the initial form action will call the server action by including a hidden input field in the form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"$ACTION_ID_/Users/lazarv/Projects/tutorials/todo/src/actions.ts#deleteTodo"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The framework will resolve this &lt;code&gt;$ACTION_ID_&lt;/code&gt; prefixed path to the server action and it will call our server action function!&lt;/p&gt;

&lt;h2&gt;
  
  
  Server actions
&lt;/h2&gt;

&lt;p&gt;We will use server actions to implement all functionality of our Todo app. This is the most complex part of the app, but don’t shy away, it’s still really very simple, let’s create &lt;strong&gt;src/actions.ts&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;redirect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@lazarv/react-server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;better-sqlite3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;zod&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;db.sqlite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CREATE TABLE IF NOT EXISTS todos (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addTodoSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;zod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;zod&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Title must be at least 3 characters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Title must be at most 100 characters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refine&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Title is required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deleteTodoSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;zod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;zod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;addTodoSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INSERT INTO todos(title) VALUES (?)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;allTodos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM todos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deleteTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;deleteTodoSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DELETE FROM todos WHERE id = ?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first line of this file, we instrument the framework to treat this file as a server action module using the &lt;code&gt;“use server”;&lt;/code&gt; directive. All exported async functions will be available for us to use as server actions.&lt;/p&gt;

&lt;p&gt;We initialize the Sqlite database on module import and create Zod schemas for item add and delete operations.&lt;/p&gt;

&lt;p&gt;In all server actions, you will receive a &lt;code&gt;FormData&lt;/code&gt; instance, including all the fields we define in the forms. We &lt;code&gt;safeParse&lt;/code&gt; these after converting to JavaScript objects using &lt;code&gt;Object.fromEntries&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If Zod validation fails, we throw the validation issues as an error.&lt;/p&gt;

&lt;p&gt;On success, we run a database command to INSERT or DELETE the Todo item.&lt;/p&gt;

&lt;p&gt;At the end, we are using &lt;code&gt;redirect&lt;/code&gt; to navigate the user back from the server action call. This is needed as we don’t want the user to use a browser page refresh to create or delete the Todo item again, reusing the form submit.&lt;/p&gt;

&lt;p&gt;We also implemented the &lt;code&gt;allTodos&lt;/code&gt; function here, to have all the storage related code in a single file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add new item
&lt;/h2&gt;

&lt;p&gt;To implement the AddTodo component, create an &lt;strong&gt;src/AddTodo.tsx&lt;/strong&gt; file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useActionState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@lazarv/react-server/router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ZodIssue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addTodo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./actions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AddTodo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useActionState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
    &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ZodIssue&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;addTodo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-gray-50 border border-gray-300 text-gray-900 rounded-lg p-2.5"&lt;/span&gt;
          &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;?.(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;autoFocus&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-white bg-blue-700 hover:bg-blue-800 rounded-lg px-5 py-2 mb-2 text-center"&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Submit
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;?.(({&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-red-50 border rounded-lg border-red-500 text-red-500 p-2.5 mb-2"&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-red-50 border rounded-lg border-red-500 text-red-500 p-2.5"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We already know, how to use server actions from a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;. But what about the result of our server action call? &lt;code&gt;useActionState&lt;/code&gt; to the rescue!&lt;/p&gt;

&lt;p&gt;By passing the &lt;code&gt;addTodo&lt;/code&gt; server action function reference to &lt;code&gt;useActionState&lt;/code&gt; , we can get the result of the server action call when this specific server action was called, so we can collect the &lt;code&gt;error&lt;/code&gt; result. This will be the Zod error issues we thrown in the add server action. So we can iterate on all Zod validation issues here and render validation error messages on the server side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production build
&lt;/h2&gt;

&lt;p&gt;During using the development server, you can notice that the page loaded some JavaScript modules in the browser. This is only used for Hot Module Replacement. In a production build, only the document and a CSS asset will be loaded in the browser.&lt;/p&gt;

&lt;p&gt;To build for production, run &lt;code&gt;pnpm build&lt;/code&gt; and then you can start the production server using &lt;code&gt;pnpm start&lt;/code&gt; . &lt;/p&gt;

&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;That’s it! We have a working small Todo example. You can also find the example on &lt;a href="https://github.com/lazarv/react-server/tree/main/examples/todo" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. By using the above approach, it will be easy for you to add a Todo item update feature, marking an item as completed. I hope you had fun and you will like the developer experience the &lt;a href="https://react-server.dev" rel="noopener noreferrer"&gt;@lazarv/react-server&lt;/a&gt; framework provides! There are a lot of other exciting features provided by React and the framework itself! We don’t used any client components here, that will be in another tutorial. The documentation site of &lt;code&gt;@lazarv/react-server&lt;/code&gt; was created using the framework and it’s build and deployment to Vercel takes about 5s! Because the framework uses Vite, the developer experience is blazing-fast!&lt;/p&gt;

</description>
      <category>react</category>
      <category>ssr</category>
      <category>reactserver</category>
      <category>vite</category>
    </item>
    <item>
      <title>let vs const in JavaScript aka why don't you learn a bit of C?</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Wed, 08 May 2024 18:54:52 +0000</pubDate>
      <link>https://forem.com/lazarv/let-vs-const-in-javascript-aka-why-dont-you-learn-a-bit-of-c-1c1d</link>
      <guid>https://forem.com/lazarv/let-vs-const-in-javascript-aka-why-dont-you-learn-a-bit-of-c-1c1d</guid>
      <description>&lt;p&gt;There's a raging war in the JavaScript community about when to use &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt; and which one should not be used. Which is ridiculous. Some major JavaScript developers are blaming &lt;code&gt;const&lt;/code&gt; as it’s not useful because you can still mutate the value in an object referenced by a &lt;code&gt;const&lt;/code&gt; variable. Let’s get a deeper look on this and some background on from where we are coming from.&lt;/p&gt;

&lt;h2&gt;
  
  
  var
&lt;/h2&gt;

&lt;p&gt;First, there was &lt;code&gt;var&lt;/code&gt;. Before ES6 you used &lt;code&gt;var&lt;/code&gt; only for variable declarations. But it was sometimes hard to understand what’s happening, because of hoisting. Hoisting means that basically all of your variable declarations are moved to the top of your scope, declaration position is ignored. So you can define your variable later in code and use your variable before declaration. Mind blowing, right? 🤯&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 42&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example just works. Hoisting will move the &lt;code&gt;var x;&lt;/code&gt; to the top and that’s how you can use the &lt;code&gt;x&lt;/code&gt; variable anywhere in the scope. Although variable initialization is not working the same way, as only the variable declaration is hoisted, not the initialization. So the following will result in &lt;code&gt;Nan&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This behaviour is surely hard to understand cognitively and hard to maintain. So we moved over with ES6 to use &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  let
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;let&lt;/code&gt; keyword is easy to describe. You just need to forget about hoisting and it works the same way as &lt;code&gt;var&lt;/code&gt; . You can re-assign any value to the variable at any point.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ReferenceError: Cannot access 'x' before initialization&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of &lt;code&gt;let&lt;/code&gt; variable declarations are no longer hoisted, the above code will not work and will throw an error when you’re trying to use &lt;code&gt;x&lt;/code&gt; before initialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we re-assign a new value to &lt;code&gt;x&lt;/code&gt;. Variable initialization set the value to &lt;code&gt;x&lt;/code&gt; to be &lt;code&gt;0&lt;/code&gt;. Then we mutated the value of &lt;code&gt;x&lt;/code&gt; and so we got &lt;code&gt;1&lt;/code&gt; as a result on the console. Let’s continue to &lt;code&gt;const&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  const
&lt;/h2&gt;

&lt;p&gt;ES6 also introduced the &lt;code&gt;const&lt;/code&gt; keyword for variable declaration. This already seems to be off, as a constant is not a variable. But the definition of “variable” explains some parts already:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A variable in programming languages is a named storage location in computer memory that holds a data value. It is characterized by an identifier, which uniquely identifies it within the program. Variables can represent various types of data, such as integers, floating-point numbers, characters, or complex data structures. The value stored in a variable can change during the execution of the program, hence the term 'variable.' Programmers use variables to store and manipulate data, enabling dynamic behavior and flexibility in their programs.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So variables are basically just identifiers to a slot in memory. When you use &lt;code&gt;var&lt;/code&gt; or &lt;code&gt;let&lt;/code&gt; the JavaScript runtime engine will let you change the value of that slot in memory. But when you use &lt;code&gt;const&lt;/code&gt;, you are instructing the JavaScript runtime engine to prevent any change of the variable, so you can’t update the memory identified by that variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: Assignment to constant variable.&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can only set the value to a &lt;code&gt;const&lt;/code&gt; variable at initialization time. &lt;code&gt;const&lt;/code&gt; variables are also not hoisted, the same way like &lt;code&gt;let&lt;/code&gt; variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  The “problem” with const…
&lt;/h2&gt;

&lt;p&gt;is that if your &lt;code&gt;const&lt;/code&gt; variable is a reference type, like an object, array or function, you can’t change the value of the variable, but you can mutate the value it’s referencing to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will perfectly work. But why? Is &lt;code&gt;const&lt;/code&gt; not preventing mutation? It is! But only for the &lt;code&gt;x&lt;/code&gt; variable. But why? Because &lt;code&gt;x&lt;/code&gt; is a reference only to the object! With other maybe familiar words: it’s a pointer!&lt;/p&gt;

&lt;p&gt;If we go back in time to the dark ages of programming, when developers used the “C” programming language to create awesome apps (most games of the ‘90s were developed by using C and Assembly), we can understand what’s happening here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nx"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;int&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Declaring a constant pointer to an integer&lt;/span&gt;

    &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Initial value: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Initial value: 5&lt;/span&gt;

    &lt;span class="c1"&gt;// Attempting to modify the value through the const pointer&lt;/span&gt;
    &lt;span class="c1"&gt;//*ptr = 10; // This line will result in a compilation error&lt;/span&gt;

    &lt;span class="c1"&gt;// However, we can still modify the underlying value using a non-const pointer&lt;/span&gt;
    &lt;span class="nx"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;mutablePtr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;mutablePtr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Modified value: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Modified value: 10&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In C, you need to cast the const pointer to be able to change it, but as the const variable is only an identifier to a slot in memory, when you convince the compiler you are allowed to change the memory identified by the variable, well, you can do it! It’s just memory!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Define a struct&lt;/span&gt;
&lt;span class="nx"&gt;struct&lt;/span&gt; &lt;span class="nx"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;int&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;int&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create an instance of struct Point&lt;/span&gt;
    &lt;span class="nx"&gt;struct&lt;/span&gt; &lt;span class="nx"&gt;Point&lt;/span&gt; &lt;span class="nx"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Declare a const pointer to a struct Point&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;struct&lt;/span&gt; &lt;span class="nx"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;point&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Initial values: (%d, %d)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Initial values: (5, 10)&lt;/span&gt;

    &lt;span class="c1"&gt;// Attempting to modify the values through the const pointer&lt;/span&gt;
    &lt;span class="c1"&gt;// ptr-&amp;gt;x = 10; // This line will result in a compilation error&lt;/span&gt;

    &lt;span class="c1"&gt;// However, we can still modify the underlying values using a non-const pointer&lt;/span&gt;
    &lt;span class="nx"&gt;struct&lt;/span&gt; &lt;span class="nx"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;mutablePtr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;struct&lt;/span&gt; &lt;span class="nx"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;mutablePtr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;mutablePtr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Modified values: (%d, %d)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Modified values: (10, 20)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works for structs too, which is most close to what an object in JavaScript is. In JavaScript, your object represents a data structure in memory. As you are not specifying this object as non-mutable by using &lt;code&gt;Object.freeze&lt;/code&gt; , you can mutate the values held in that object. Keep in mind, that nested objects are basically just pointers too and &lt;code&gt;Object.freeze&lt;/code&gt; is only work for that single object you are freezing. For nested objects, you need to freeze every object used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 42&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will just work, but when you change the code to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will get back the same value as before, &lt;code&gt;x.a.b&lt;/code&gt; will be &lt;code&gt;0&lt;/code&gt;. I admit, that this is still not the same as using a primitive &lt;code&gt;const&lt;/code&gt; variable as the above will not throw an error, it just silently doesn't change the value of &lt;code&gt;x.a.b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So in case of a JavaScript &lt;code&gt;const&lt;/code&gt; variable, you can’t change the pointer / reference, but you change the underlying memory. It is a false assumption, that the &lt;code&gt;const&lt;/code&gt; specifier will affect the referenced object too. Why would it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Cognitive load
&lt;/h2&gt;

&lt;p&gt;What’s the role of &lt;code&gt;let&lt;/code&gt; when you want immutability all the time? Marking and flagging all involved parties that you want to change the value of the variable at some point in your code! This doesn’t mean that it has to be another developer, it can be a static analysis tool or AI, anyone or anything that can understand code.&lt;/p&gt;

&lt;p&gt;During code reviews &lt;code&gt;let&lt;/code&gt; will help the reviewer to take special care about handling the variable. When I encounter such a case I instantly switch into questioning the authors code, why there’s a &lt;code&gt;let&lt;/code&gt; variable. Is there any reason to use &lt;code&gt;let&lt;/code&gt;? At any point is the value mutated? Why is it mutated?&lt;/p&gt;

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

&lt;p&gt;As every language feature, &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; are just tools the developer can use. No one is forced to use &lt;code&gt;const&lt;/code&gt;. It is not necessary to do so. But it provides values and by not using it, you miss those values.&lt;/p&gt;

&lt;p&gt;What’s the value in saving 2 characters? Time? Code completion and any type of artificial help in typing in the variable definition makes this obsolete. Size of the bundle used? 2kb, maybe 20k in case of a very large library? While we are watching billions of videos online?&lt;/p&gt;

&lt;p&gt;It would be better to review over-engineered and unnecessary architectures or tech stacks we use, than complaining about using &lt;code&gt;const&lt;/code&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A new experimental meta-framework for React</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Thu, 28 Sep 2023 15:34:21 +0000</pubDate>
      <link>https://forem.com/lazarv/a-new-experimental-meta-framework-for-react-247i</link>
      <guid>https://forem.com/lazarv/a-new-experimental-meta-framework-for-react-247i</guid>
      <description>&lt;p&gt;I was following the new React server-side rendering features for years now, since React 18. Everything started with using streaming and &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; for rendering the document for the user. I had experiments in the past using React 18 streaming rendering using &lt;strong&gt;vite-plugin-ssr&lt;/strong&gt;. Then came Next.js 13 and React Server Components were unleashed. But it didn't stop there. Server Actions! What awesome features these are from the React team!&lt;/p&gt;

&lt;h2&gt;
  
  
  A new and better PHP
&lt;/h2&gt;

&lt;p&gt;It's fashionable to say that PHP is bad. But reality is that it's not and it will not die in the foreseeable future. But what's the issue with PHP? Switching language and context when you need something to work in the browser! There are a myriad of ways to handle the issue. But can you imagine a solution, where you get all the benefits of PHP AND you can create components which are running only in the browser in an instant? We are mostly talking about React Server Components, but the star of the show for me is mixing server and client components in the same React tree and it magically works!&lt;/p&gt;

&lt;h2&gt;
  
  
  Your BFF!
&lt;/h2&gt;

&lt;p&gt;Another hot topic in web development is &lt;strong&gt;tRPC&lt;/strong&gt;, which is a fantastic tool. But for a backend-for-frontend API, it's a bit of an overkill. Instead of creating the setup for tRPC and using its client, wouldn't be better to just use your functions as references and pass them to the browser, to be called as a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;'s action or just programmatically from your client components? Deal done, this is Server Actions!&lt;/p&gt;

&lt;p&gt;The first implementation of these React features were done by Next.js. Not surprising as these teams are working in close collaboration. But what to do if you're not fully satisfied with Next.js? What are your options?&lt;/p&gt;

&lt;p&gt;In the past few months, I eagerly dived-in into this topic and the result is &lt;a href="https://github.com/lazarv/react-server" rel="noopener noreferrer"&gt;@lazarv/react-server&lt;/a&gt;, my own new experimental React meta-framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  In search of flexibility
&lt;/h2&gt;

&lt;p&gt;I very much like React's approach on how un-opinionated it is and supporting the "bring-your-own" mindset for your app. Next.js was always too rigid for me, so I wanted to see something configurable to the last bit possible.&lt;/p&gt;

&lt;p&gt;I wanted to use the following 2 major tech with these new React features: &lt;strong&gt;ES modules&lt;/strong&gt; and &lt;strong&gt;Vite&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For a long time now, I'm a huge advocate of ES modules. It's almost a shame that CommonJS is still here, despite the effort people are putting into using ES modules wherever possible. ES modules are supported by all browsers natively and fits for client components so well.&lt;/p&gt;

&lt;p&gt;Vite is providing the best developer experience so much, that almost everyone is using it now. Astro, Nuxt, SolidStart, SvelteKit to mention just a few. Vite is highly customisable and extensible by using plugins. My first encounter with Vite was when I implemented my first streaming React SSR using vite-plugin-ssr and I always use it since then whenever possible. Vite and ES modules are best friends as Vite makes working with ES modules an ease.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Do you ever dreamed about using a server-side rendering framework easy as a simple node.js script? With &lt;code&gt;@lazarv/react-server&lt;/code&gt;, it's possible.&lt;/p&gt;

&lt;p&gt;Let's setup the environment for our first app! We will use &lt;strong&gt;pnpm&lt;/strong&gt; as it's the best and fastest package manager for node.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
pnpm init
pnpm add @lazarv/react-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now believe it or not, we're ready to implement our app. Just create a new entrypoint for the app in &lt;code&gt;./App.jsx&lt;/code&gt; or choose a name you like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you're ready to start this app using &lt;code&gt;@lazarv/react-server&lt;/code&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nb"&gt;exec &lt;/span&gt;react-server ./App.jsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This almost feels like using &lt;code&gt;node ./App.jsx&lt;/code&gt;, doesn't it? The framework has so many features it would be hard to include everything right away, so stay tuned for more! Check out the repo in the meanwhile and try to run the examples in the repo. You can start the Photos example as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/lazarv/react-server
&lt;span class="nb"&gt;cd &lt;/span&gt;react-server
pnpm &lt;span class="nb"&gt;install
&lt;/span&gt;pnpm &lt;span class="nt"&gt;--filter&lt;/span&gt; ./examples/photos dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Future of &lt;code&gt;@lazarv/react-server&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;As this is only a personal experimental framework, I would only suggest to give it a go, but only use this for your own learning about the future of React. Which is still bright and awesome!&lt;/p&gt;

&lt;p&gt;Please provide feedback on GitHub, here in dev.to or on Twitter/X. Every feedback is much appreciated and adds value to this project. Thanks!&lt;/p&gt;

&lt;p&gt;I'll work on documentation and bug fixes for now, so please be patient and give the repo a star on GitHub to get notified on what's happening with this framework.&lt;/p&gt;

&lt;p&gt;Maybe this will grow into something more.&lt;/p&gt;

&lt;p&gt;Much more...&lt;/p&gt;

</description>
    </item>
    <item>
      <title>React Server Components without any frameworks</title>
      <dc:creator>Viktor Lázár</dc:creator>
      <pubDate>Fri, 07 Jul 2023 15:21:00 +0000</pubDate>
      <link>https://forem.com/one-beyond/react-server-components-without-any-frameworks-5a8p</link>
      <guid>https://forem.com/one-beyond/react-server-components-without-any-frameworks-5a8p</guid>
      <description>&lt;p&gt;Starting with Next.js 13 developers can access the power of React Server Components (let's just use RSC from now on). But if you don't want to use Next.js and you want to start to use RSC out of the box, then how should you start?&lt;/p&gt;

&lt;h1&gt;
  
  
  Dependencies
&lt;/h1&gt;

&lt;p&gt;You need to use the experimental versions of &lt;code&gt;react&lt;/code&gt;, &lt;code&gt;react-dom&lt;/code&gt; and &lt;code&gt;react-server-dom-webpack&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's start up a new project and install these. We will use &lt;code&gt;pnpm&lt;/code&gt;, as it is now the best and most loved choice. Also for quick setup, we will use &lt;a href="https://vitejs.dev" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; for the client side and &lt;a href="https://github.com/hattipjs/hattip" rel="noopener noreferrer"&gt;HatTip&lt;/a&gt; for our backend handler for more convenient readable stream handling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;hello-rsc
&lt;span class="nb"&gt;cd &lt;/span&gt;hello-rsc
pnpm init
pnpm add react@experimental react-dom@experimental react-server-dom-webpack@experimental vite @vitejs/plugin-react @hattip/core @hattip/adapter-node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;

&lt;p&gt;To start to work with SSR rendering with Vite, we need to create some files to get started with.&lt;/p&gt;

&lt;h3&gt;
  
  
   SSR
&lt;/h3&gt;

&lt;p&gt;We will need an &lt;code&gt;index.html&lt;/code&gt; file, which will be our SSR HTML template, which will load the client entry script. This is very-very minimal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"index.jsx"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To start our SSR enabled Vite development server, let's create an &lt;code&gt;index.mjs&lt;/code&gt; file, where we will instantiate a Vite development server in middleware mode and with &lt;strong&gt;"ssr"&lt;/strong&gt; as application type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createMiddleware&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hattip/adapter-node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;createViteDevServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readFile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:fs/promises&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viteDevServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createViteDevServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;middlewareMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;appType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to preload our &lt;code&gt;index.html&lt;/code&gt; for later usage. So let's read up the file as it is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following HatTip handler will be our router to handle requests which accepts an RSC response. If the &lt;code&gt;Accept&lt;/code&gt; header includes the &lt;code&gt;text/x-component&lt;/code&gt; MIME type, then we know that the client needs the response in RSC format.&lt;/p&gt;

&lt;p&gt;The RSC format is a JSON-like format which includes all the React elements the client will render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0:"$L1"
1:[["$","h1",null,{"children":"Hello World!"}],["$","h2",null,{"children":["Darwin"," ","x64"," ","22.5.0"]}],"2023-07-07T12:40:30.880Z"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our implementation loads the &lt;code&gt;rsc.jsx&lt;/code&gt; SSR module using Vite and uses the &lt;code&gt;render&lt;/code&gt; function which will render the RSC into a readable stream. We also do some basic error handling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ssr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accept&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/x-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;viteDevServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ssrLoadModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./rsc.jsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/x-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;viteDevServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transformIndexHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the end of this, we only need to start listening to requests using the Vite development server. As the&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;viteDevServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;viteDevServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;listening&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Listening on http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  React Server Component
&lt;/h3&gt;

&lt;p&gt;How the &lt;code&gt;rsc.jsx&lt;/code&gt; looks like? It's really very simple. The main imported module we need to watch out for is the &lt;code&gt;react-server-dom-webpack/server.edge&lt;/code&gt;. Our &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; component is an async function, so we can use &lt;code&gt;await&lt;/code&gt; inside of it and at the end, just return JSX where we can also include server-side only functionality, so we give the client information about our OS and the current time. But first, we delay the response for a bit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;renderToReadableStream&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server-dom-webpack/server.edge&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;OS&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:os&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;renderToReadableStream&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exported &lt;code&gt;render&lt;/code&gt; function is the one we used in the &lt;code&gt;index.mjs&lt;/code&gt; handler, loaded with Vite as an SSR module.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client
&lt;/h3&gt;

&lt;p&gt;The last part we need to implement is our client entry, where we create our React root to render the RSC response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRoot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createFromFetch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-server-dom-webpack/client.browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rsc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;rsc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;rsc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFromFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/x-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rsc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Loading..."&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to add a &lt;code&gt;Suspense&lt;/code&gt; around our &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; component so it will show a fallback loading message while the client receives the RSC response.&lt;/p&gt;

&lt;p&gt;We also need to "cache" the result of &lt;code&gt;createFromFetch&lt;/code&gt; as we don't want this to be fired more than once and it always should be the same, so React can handle the &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; component properly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Future enhancement
&lt;/h3&gt;

&lt;p&gt;Currently, our RSC rendering is not supporting client components (&lt;code&gt;'use client'&lt;/code&gt;), only server-side rendered elements. We also don't support server actions in this implementation. These are much more advanced topics and you should use Next.js 13 for this or another meta-framework supporting these features.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Surely, this is only a &lt;em&gt;"Hello World!"&lt;/em&gt; level implementation and could be enhanced, but maybe this is a good starting point when you want to start playing with some low-level implementation regarding React Server Components.&lt;/p&gt;

&lt;p&gt;You can access the code at &lt;a href="https://github.com/lazarv/hello-rsc" rel="noopener noreferrer"&gt;this repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading, please click on follow and have a nice day!&lt;/p&gt;

</description>
      <category>react</category>
    </item>
  </channel>
</rss>
