"Towards React Server Components in Clojure", Roman Liutikov

fwdays 34 views 27 slides Oct 18, 2025
Slide 1
Slide 1 of 27
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27

About This Presentation

We will take a look inside React Server Components using an implementation in the Clojure programming language. You will learn what the “magic” of server components looks like under the hood, how component streaming works, and whether it’s really possible to send a Promise over an HTTP request...


Slide Content

NN
TOWARDS REACT SERVE N)
COMPONENTS IN CLOJURE

[UKR]

POMAH JINTIKOB
SkyDefenders

React
& fwdays October 18, 2

{ste

={false}

{(step !== 1 || isRejectel
<DesktopOnly>

<Donelnf:
<AudioInfo

={audioFi

={audioFi

={aud

</DoneInfo>
</DesktopOnly>
) : null}
<CardChevron
{step === 1 88 (
<React. Fragment>
{(!hasAudiofile || ist
<FilePicker
=(isRejected;
={aul
{file
setFile(file);
»

React + SSR

,
| <—html
1
ı

| <— runtime

Shell + SPA

browser

\

< html shell —

1
¡$ runtime —__
AT

Dynamic Islands

React Server Components

MW
React
fwdays

(did })

={() æ Likearticle(id)}>Like</

(Lid Ft
{ title, content } =

<hb{title}</h1>
<p>{content}</p>

Y >

a website with dynamic islands

It's fast!

render
interactive

render <A>
interactive >

…Or is it?

HTML streaming in React

id

unction Article({ id, title, content }) {
return (
<article>
1>{titte}/h1>
ontent)
uspense fallback={<Spinner A
<Comments id={id} />
Sus
article:

5

React
fwdays

Runs blocking 1/0 concurrently

HTML streaming in React

template id ></template>
<span>fallback</span>

‘span>DATA</ span></ div>
5 );</script>

React
fwdays

Flight

serialization format

<Button title="btn">press me</Button>
</div>

hunk. js", "Button", false]
div" null, {*title": "hello", "children":[["$", null,{:title "btn"

press

Serialize promises!

await
return

$","div" null, 3 an" ‚null,f{"children":["$a1"]}]]}]
uo"

Navigation

React
fwdays

Navigation with RSC feels slow

press a link

“request Flight data

streamed response

£--

client server

SAV

React
fwdays

Strategies to speedup navigation

prefetch all routes
prefetch visible links
prefetch links near mouse pointer
*caching

React
fwdays

Mutations

React
fwdays

RPC

({ id }) {

={() [Uikearticte(id))>Like</

({ id }) {

nst { title, content } =

<hi>ftitle}</h1>
<p>{content}</p>

>

Enter Clojure

® = &.
© aaa

days

HUMANITY HAD BEEN SAVED! DOUG THE DEVELOPER AND
AND THE OTHERS COULD NOW RETURN TO THEIR
PROGRAMMING, NO LONGER IN FEAR OF BUGS, BY
LEARNING THE LESSONS OF THE TEN GUILDS OF THE
LANO OF LISP, PROGRAMS COULD BECOME RICHER AND
MORE ROBUST THAN EVER BEFORE:

React component

= = =
in ClojureScript
stories [{ [path]}]
[data ( path)]
[d data]
($ story { ( d) d}))))
SOV
React

fwdays

(defui story [{:keys [data]}]
(let [{:keys [id by score time title url kids]} data]

($ ui/vote-btn {:id id :score score})
0)

(defui “:client vote-btn [{:keys [id score]}] RSC
($ :button {:on-click #actions/vote id score)}
(str "Vote " score)))

in ClojureScript

(defaction vote [id]
(sql/exec {:update :stories,

:set {:score [:+ :score 1]},

:where [ :id id]})) ANY

React
fwdays

Suspense + 1/0 + Concurrency

(defui suspense [{:keys [fallback children]}]
(collect (async/thread (serialize children)))
fallback)

(async/go-loop [chans collected-channels]
(if (empty? chans)
(close-connection)
(let [[html chan] (async/alts! chans)]

(push-chunk html) SO)

(recur (disj chans chan)))))

React
fwdays

Bonus: Error reporting

class java lang IndexOutOfBoundsException

Av

React
fwdays

That's all folks Y

Sandbox Blog Telegram