Skip to content

Commit

Permalink
Fix server side rendering (#730)
Browse files Browse the repository at this point in the history
Fixes #706.
  • Loading branch information
borkdude authored Nov 12, 2024
1 parent c3ae5b3 commit d9cab25
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 16 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ jobs:
- name: Run Playwright tests against static assets
run: |
bb test:static-app :sha ${{ github.sha }} :skip-install true
bb test:static-app :skip-install true :url https://snapshots.nextjournal.com/clerk/book/${{ github.sha }}/book/index.html :index false :selector "span:has-text(\"Book of Clerk\")"
bb test:static-app :skip-install true :url https://snapshots.nextjournal.com/clerk/book/${{ github.sha }}/book/index.html :index false :selector "h1:has-text(\"Book of Clerk\")"
bb test:static-app :skip-install true :url https://snapshots.nextjournal.com/clerk-ssr/build/${{ github.sha }}/index.html :index false :selector "h1:has-text(\"Rule 30\")"
deploy:
needs: [build-and-upload-viewer-resources, test]
Expand Down
36 changes: 27 additions & 9 deletions src/nextjournal/clerk/builder.clj
Original file line number Diff line number Diff line change
Expand Up @@ -163,18 +163,36 @@
:path->doc path->doc
:paths (vec (keys path->doc)))))

(defn- node-ssr!
[{:keys [viewer-js state]
:or {viewer-js
;; for local REPL testing
"./public/js/viewer.js"}}]
(sh {:in (str "import '" viewer-js "';"
"globalThis.CLERK_SSR = true;"
"console.log(nextjournal.clerk.sci_env.ssr(" (pr-str (pr-str state)) "))")}
"node"
"--abort-on-uncaught-exception"
"--experimental-network-imports"
"--input-type=module"
"--trace-warnings"))

(comment
(declare so) ;; captured in REPL in ssr! function
(node-ssr! {:state so})
)

(defn ssr!
"Shells out to node to generate server-side-rendered html."
[{:as static-app-opts :keys [report-fn resource->url]}]
(report-fn {:stage :ssr})
(let [{duration :time-ms :keys [result]}
(eval/time-ms (sh {:in (str "import '" (resource->url "/js/viewer.js") "';"
"console.log(nextjournal.clerk.sci_env.ssr(" (pr-str (pr-str static-app-opts)) "))")}
"node"
"--abort-on-uncaught-exception"
"--experimental-network-imports"
"--input-type=module"
"--trace-warnings"))
(let [doc (get (:path->doc static-app-opts) (:current-path static-app-opts))
static-app-opts (-> (assoc static-app-opts :doc doc)
(dissoc :path->doc)
(assoc :render-router :serve))
{duration :time-ms :keys [result]}
(eval/time-ms (node-ssr! {:viewer-js (resource->url "/js/viewer.js")
:state static-app-opts}))
{:keys [out err exit]} result]
(if (= 0 exit)
(do
Expand Down Expand Up @@ -203,9 +221,9 @@
(spit (fs/file out-path (str (or (not-empty path) "index") ".edn"))
(viewer/->edn doc))
(spit out-html (view/->html (-> static-app-opts
(dissoc :path->doc)
(assoc :current-path path)
(cond-> ssr? ssr!)
(dissoc :path->doc)
cleanup))))))
(when browse?
(browse/browse-url (if-let [server-url (and (= out-path "public/build") (webserver/server-url))]
Expand Down
3 changes: 2 additions & 1 deletion src/nextjournal/clerk/render.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,8 @@
:status (.-status r)
:headers (.-headers r)})))))
(then read-response+show-progress)
(then (fn [edn] (set-state! {:doc (read-string edn)}) {:ok true}))
(then (fn [edn]
(set-state! {:doc (read-string edn)}) {:ok true}))
(catch (fn [e] (js/console.error "Fetch failed" e)
(set-state! {:doc {:nextjournal/viewer {:render-fn (constantly [:<>])} ;; FIXME: make :error top level on state
:nextjournal/value {:error (viewer/present e)}}})
Expand Down
4 changes: 3 additions & 1 deletion src/nextjournal/clerk/render/hooks.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@
(defn use-ref
"React hook: useRef. Can also be used like an atom."
([] (use-ref nil))
([init] (specify-atom! (react/useRef init))))
([init] (if (unchecked-get js/globalThis "CLERK_SSR")
(atom init)
(specify-atom! (react/useRef init)))))

(defn ^:private eval-fn
"Invoke (f x) if f is a function, otherwise return f"
Expand Down
1 change: 1 addition & 0 deletions src/nextjournal/clerk/sci_env.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
[applied-science.js-interop :as j]
[cljs.math]
[cljs.reader]
[cljs.repl]
[clojure.string :as str]
[edamame.core :as edamame]
[goog.object]
Expand Down
12 changes: 8 additions & 4 deletions ui_tests/playwright_tests.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,20 @@
(p/do (goto page url)
(.waitForLoadState page "networkidle")
(p/let [selector (or (:selector @!opts) "div")
loc (.locator page selector)
loc (.first loc #js {:timeout 10000})]
(is (.isVisible loc #js {:timeout 10000})))))
_ (prn :selector selector)
loc (.locator page selector #js {:timeout 10000})
loc (.first loc #js {:timeout 10000})
_ (.waitFor loc #js {:state "visible"})
visible? (.isVisible loc)]
(is visible?))))
([page url link]
(p/let [txt (.innerText link)]
(println "Visiting" (str url "#/" txt))
(p/do (.click link)
(p/let [loc (.locator page "div")
loc (.first loc #js {:timeout 10000})
visible? (.isVisible loc #js {:timeout 10000})]
_ (.waitFor loc #js {:state "visible"})
visible? (.isVisible loc)]
(is visible?))))))

(deftest index-page-test
Expand Down

0 comments on commit d9cab25

Please sign in to comment.