Server streams HTML shell with ~suspense placeholders immediately, then sends resolution <script> chunks as async IO completes. Browser renders loading skeletons instantly, replacing them with real content as data arrives via __sxResolve(). - defpage :stream true opts pages into streaming response - ~suspense component renders fallback with data-suspense attr - resolve-suspense in boot.sx (spec) + bootstrapped to sx-browser.js - __sxPending queue handles resolution before sx-browser.js loads - execute_page_streaming() async generator with concurrent IO tasks - Streaming demo page at /isomorphism/streaming with 1.5s simulated delay Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
40 lines
1.7 KiB
Plaintext
40 lines
1.7 KiB
Plaintext
(defcomp ~base-shell (&key title asset-url &rest children)
|
|
(<>
|
|
(raw! "<!doctype html>")
|
|
(html :lang "en"
|
|
(head
|
|
(meta :charset "utf-8")
|
|
(meta :name "viewport" :content "width=device-width, initial-scale=1")
|
|
(title title)
|
|
(style
|
|
"body{margin:0;min-height:100vh;display:flex;align-items:center;"
|
|
"justify-content:center;font-family:system-ui,sans-serif;"
|
|
"background:#fafaf9;color:#1c1917}")
|
|
(link :rel "stylesheet" :type "text/css" :href (str asset-url "/styles/tw.css"))
|
|
(link :rel "stylesheet" :href (str asset-url "/fontawesome/css/all.min.css")))
|
|
(body :class "bg-stone-50 text-stone-900"
|
|
children))))
|
|
|
|
;; ---------------------------------------------------------------------------
|
|
;; Suspense — streaming placeholder that renders fallback until resolved.
|
|
;;
|
|
;; Server-side: rendered in the initial streaming chunk with a fallback.
|
|
;; Client-side: replaced when the server streams a resolution chunk via
|
|
;; <script>__sxResolve("id", "(resolved sx ...)")</script>
|
|
;; ---------------------------------------------------------------------------
|
|
|
|
(defcomp ~suspense (&key id fallback &rest children)
|
|
(div :id (str "sx-suspense-" id)
|
|
:data-suspense id
|
|
:style "display:contents"
|
|
(if children children fallback)))
|
|
|
|
(defcomp ~error-page (&key title message image asset-url)
|
|
(~base-shell :title title :asset-url asset-url
|
|
(div :class "text-center p-8 max-w-lg mx-auto"
|
|
(div :class "font-bold text-2xl md:text-4xl text-red-500 mb-4"
|
|
(div message))
|
|
(when image
|
|
(div :class "flex justify-center"
|
|
(img :src image :width "300" :height "300"))))))
|