Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e9ce789
rsc initial pass
roman01la May 5, 2025
2ccda0b
wip
roman01la May 8, 2025
b587c7d
wip
roman01la May 11, 2025
4ec091e
server action as a prop to client component
roman01la May 11, 2025
47419fb
server element as a prop to client component
roman01la May 11, 2025
2f7a040
server action as a prop to client component
roman01la May 11, 2025
ef716cd
wip streaming ssr with suspense
roman01la May 12, 2025
26387f8
cacheable rsc fetching & switching between ssr and spa modes
roman01la May 12, 2025
3545f17
streaming ssr with suspense
roman01la May 12, 2025
c47bdd6
wip
roman01la May 12, 2025
cf834fa
wip
roman01la May 13, 2025
a59d95d
wip
roman01la May 16, 2025
d0f1d7a
server action: partial application
roman01la May 16, 2025
baea5f2
fix tests
roman01la May 16, 2025
e3ba9a9
docs wip
roman01la May 17, 2025
ea4d043
client only components
roman01la May 17, 2025
50f362d
form action
roman01la May 18, 2025
83fbe90
wip
roman01la May 19, 2025
5a980b1
rsc movies demo
roman01la May 19, 2025
f5a450b
batched data loader
roman01la May 20, 2025
9ead0a9
rsc movies demo
roman01la May 21, 2025
10a9d4e
restructure routing
roman01la May 23, 2025
9c8f6d1
improve prefetching
roman01la May 23, 2025
7351f42
server actions: file upload
roman01la May 23, 2025
69aea90
cleanup
roman01la Jun 2, 2025
d85640d
do not expose bound args to client
roman01la Jun 2, 2025
c3c32ed
server error reporting
roman01la Jun 3, 2025
210bb50
improve error reporting
roman01la Jun 3, 2025
a6325e6
context: ssr & rsc
roman01la Jun 4, 2025
00d118b
foresight prefecthing
roman01la Jun 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.git
node_modules
core/.clojure-lsp
core/.idea
core/.cpcache
core/.shadow-cljs
core/target
core/rsc-out
core/node_modules
dom/.idea
dom/.cpcache
dom/.shadow-cljs
dom/node_modules
dom/client-test
.lsp
.github
core/app.aot
core/app.aotconf
23 changes: 23 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM clojure:tools-deps-bookworm-slim AS builder
WORKDIR /opt
COPY . .
RUN apt-get update
RUN apt-get install -y --no-install-recommends curl bash zip unzip ca-certificates
RUN rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
RUN apt-get install -y nodejs

WORKDIR /opt/core
RUN ./scripts/rsc
RUN clojure -Sdeps '{:mvn/local-repo "./.m2/repository"}' -T:build uber

FROM clojure:tools-deps-bookworm-slim AS runtime
COPY --from=builder /opt /app

RUN apt-get update
RUN apt-get install -y --no-install-recommends curl bash zip unzip ca-certificates
RUN rm -rf /var/lib/apt/lists/*

WORKDIR /app/core
EXPOSE 8080
ENTRYPOINT java -cp target/app.jar uix.rsc_example.server.core
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ npm install [email protected] [email protected] --save-dev
- [Code-splitting and React.lazy](docs/code-splitting.md)
- [Migrating from Reagent](docs/migrating-from-reagent.md)
- [Server-side rendering](docs/server-side-rendering.md)
- [Streaming SSR](docs/server-side-rendering.md#streaming-ssr)
- [React Server Components](docs/react-server-components.md)
- [Hot reloading](docs/hot-reloading.md)
- [React DevTools](docs/react-devtools.md)
- [Code linting](docs/code-linting.md)
Expand Down
1 change: 1 addition & 0 deletions core/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ resources/public/benchmark.js
target
.rebel_readline_history
out
rsc-out
index.html
node_modules
server_render_test
Expand Down
21 changes: 21 additions & 0 deletions core/build.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(ns build
(:require [clojure.tools.build.api :as b]))

(def build-dir "target")
(def class-dir (str build-dir "/classes"))
(def basis (b/create-basis {:project "deps.edn"}))
(def uber-file (str build-dir "/app.jar"))

(defn uber [_]
(b/delete {:path build-dir})
(b/copy-dir {:src-dirs ["src" "dev" "rsc-out"]
:target-dir class-dir})
(b/compile-clj {:basis basis
:src-dirs ["src" "dev"]
:class-dir class-dir
:ns-compile '[uix.rsc-example.server.core]
:compile-opts {:direct-linking true}})
(b/uber {:class-dir class-dir
:uber-file uber-file
:basis basis})
(println "Uberjar written to" uber-file))
19 changes: 15 additions & 4 deletions core/deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
com.adamrenklint/preo {:mvn/version "0.1.0"}}
:paths ["src" "resources"]
:aliases {:dev {:extra-deps {cljfmt/cljfmt {:mvn/version "0.8.0"}
clj-kondo/clj-kondo {:mvn/version "2025.02.20"}}}
clj-kondo/clj-kondo {:mvn/version "2025.02.20"}
org.clojure/clojurescript {:mvn/version "1.11.60"}
uix.dom/uix.dom {:local/root "../dom"}}}
:benchmark {:extra-paths ["benchmark"]
:extra-deps {reagent/reagent {:mvn/version "1.2.0"}
lilactown/helix {:mvn/version "0.1.10"}}}

:test {:extra-paths ["test" "dev"]
:extra-deps {org.clojure/clojure {:mvn/version "1.11.1"}
:extra-deps {org.clojure/clojure {:mvn/version "1.12.0"}
org.clojure/clojurescript {:mvn/version "1.11.60"}
thheller/shadow-cljs {:mvn/version "2.28.20"}
uix.dom/uix.dom {:local/root "../dom"}
Expand All @@ -22,7 +24,16 @@
:main-opts ["-m" "release"]}

:examples {:extra-paths ["dev"]
:extra-deps {org.clojure/clojure {:mvn/version "1.11.1"}
:extra-deps {org.clojure/clojure {:mvn/version "1.12.0"}
org.clojure/clojurescript {:mvn/version "1.11.60"}
thheller/shadow-cljs {:mvn/version "2.28.20"}
uix.dom/uix.dom {:local/root "../dom"}}}}}
metosin/reitit {:mvn/version "0.8.0"}
org.apache.commons/commons-text {:mvn/version "1.13.1"}
http-kit/http-kit {:mvn/version "2.8.0"}
compojure/compojure {:mvn/version "1.7.1"}
com.github.seancorfield/next.jdbc {:mvn/version "1.3.1002"}
org.xerial/sqlite-jdbc {:mvn/version "3.49.1.0"}
uix.dom/uix.dom {:local/root "../dom"}}}
:build {:extra-paths ["dev"]
:extra-deps {io.github.clojure/tools.build {:git/tag "v0.9.6" :git/sha "8e78bcc"}}
:ns-default build}}}
1 change: 1 addition & 0 deletions core/dev/preo/core.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(ns preo.core)
156 changes: 0 additions & 156 deletions core/dev/uix/examples.cljs

This file was deleted.

13 changes: 13 additions & 0 deletions core/dev/uix/rsc_example/actions.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(ns uix.rsc-example.actions
(:require [uix.rsc :refer [defaction]]
[uix.rsc-example.server.db :as db]))

(defaction vote [{:keys [id]}]
(Thread/sleep 1000)
(db/vote-on-story id))

(defaction update-fav [{:keys [id intent]}]
(case intent
:add (db/favs+ db/*sid* id)
:remove (db/favs- db/*sid* id))
true)
10 changes: 10 additions & 0 deletions core/dev/uix/rsc_example/client/root.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(ns uix.rsc-example.client.root
(:require [uix.dom.rsc :as dom.rsc]
[uix.rsc-example.routes :refer [routes]]
[uix.rsc-example.client.ui]))

(defn init []
(dom.rsc/render-root
{:container js/document
:routes routes
:ssr-enabled true}))
41 changes: 41 additions & 0 deletions core/dev/uix/rsc_example/client/ui.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
(ns uix.rsc-example.client.ui
(:require [uix.core :refer [defui $] :as uix]
[uix.dom :as dom]
[uix.rsc :as rsc]))

;; todo: make client any var via ^:client meta
;; in cljs? maybe scan vars in shadow?
(def say-hi
^{:rsc/id "uix.rsc-example.client.ui/say-hi"} (fn []
(prn :HEllo!)))

#?(:cljs
(uix.rsc/register-rsc-client! "uix.rsc-example.client.ui/say-hi" say-hi))

(defui ^:client vote-btn [{:keys [score label]}]
(let [{:keys [pending]} (dom/use-form-status)]
($ :button {:type :submit
:style {:text-decoration :underline
:cursor :pointer}}
(if pending
"voting"
($ :<> label " " score)))))

(defui ^:client fav-button [{:keys [liked?]}]
(let [{:keys [pending]} (dom/use-form-status)]
($ :button {:type :submit
:on-click #(when pending (.preventDefault %))
:class "font-instrumentSans font-semibold rounded-xl w-full text-xl border-[2px] py-2 px-5 group"}
($ :span {:class "group-hover:scale-105 group-active:scale-100 inline-block transition-transform duration-100"}
(cond
(and pending liked?) "Removing..."
(and pending (not liked?)) "Adding..."
liked? "Remove from favorites"
:else "Add to favorites")))))

;; ^:client turns client component into a client ref
;; when the component is used in server components tree
#_
(defui ^:client vote-btn [{:keys [score label on-vote] :as props}]
(rsc/use-client {:fallback ($ :button "Vote 0")}
($ vote-btn* props)))
17 changes: 17 additions & 0 deletions core/dev/uix/rsc_example/routes.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
(ns uix.rsc-example.routes
(:require [uix.rsc :refer [defroutes]]
#?(:clj [uix.rsc-example.server.ui :as ui])))

(defroutes routes2
[["/" {:component ui/stories :title "new"}]
["/askstories" {:component ui/stories :title "ask"}]
["/showstories" {:component ui/stories :title "show"}]
["/jobstories" {:component ui/stories :title "job"}]
["/topstories" {:component ui/stories :title "top"}]
["/beststories" {:component ui/stories :title "best"}]
["/item/:id" {:component ui/item}]])

(defroutes routes
[["/" {:component ui/home}]
["/movie/:id" {:component ui/movie}]
["/actor/:id" {:component ui/actor}]])
Loading