Liking cljdoc? Tell your friends :D

Scripts the page needs

Some of a page has to run in the browser: an outline that follows the reader as they scroll, a chart, a clock. co.multiply.tropical.script loads such code as an ES module, once per page, for the islands that need it.

(script/defscript outline
  "The page's outline, which follows the reader as they scroll."
  {:resource "app/outline.js"})

(defisland article-outline
  []
  (script/use outline)
  [:nav [:page-outline]])
  • Declared where it's used. defscript reads the module from a resource on the classpath, or takes its content as {:js string}. An island takes it up with script/use during its render, which returns the script's URL, for an expression that imports it. A module runs once per page, however many islands use it.
  • Loaded with the first frame that declares it: in the page's head if the first frame has it, or appended to the head over the stream when such an island is patched in. Datastar gives a script tag that arrives in a patch the page's nonce.
  • Served outside the routes. Wrap the app in ring/wrap-scripts, outside the routes and the session middleware. It serves each script under /tropical/, at a URL named by its var and the hash of its content, which browsers keep for good.
  • The first frame's scripts go in the head, with the nonce: [:head … (ring/scripts nonce)], or (script/tags scripts nonce) given the :scripts its :page gets, and the stream doesn't send them again. A page that leaves them out still gets them over the stream, a little later. One that renders them without the nonce breaks them: a module blocked once stays failed for the page.
  • Don't draw into the island. When the island is sent again, Datastar morphs its elements' children back to the server's, undoing what a script put there. A web component draws into its shadow root, which the morph doesn't reach. One made with Datastar's Rocket loads this way too (Components with Rocket).
  • A page keeps what it loaded. An edited script gets a new URL, but customElements.define won't redefine a name, and a module runs again beside the old one. So a page reloads when its stream connects to a server on which a script has changed since the page loaded: after a deploy that changes one, or in development, after session/close-all! (Reloading code in development). In development, a script whose resource is a file is read again when the file changes.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close