Closed tiye closed 7 years ago
This is a cool idea, but I don't think it belongs in Lumo.
Happy to see this done as a library and to provide the necessary API hooks for it to work.
Do you have any clue on how to build this kind of thing with lumo APIs now?
I haven't given it any thought yet, so no :-)
I was exactly thinking about this yesterday.
In boot
, the watch
task triggers the re-trigger (:smile:) of tasks. Therefore if we want to accomplish server side reloading somebody would need to build a simple task that "speaks with" lumo at every re-trigger, sending the changed namespaces (source of inspiration) and then letting lumo do the require
+ on-jsload
.
Typically this is achieved with a websocket server (both boot-reload
and lein-figwheel
) do this.
I agree that all this should be in a separate library. It would actually be great to package common code (the websocket lib and the comm protocol and maybe the browser client) in one library so that it can be used in other projects as well.
Suppose I have to files,
main.cljs
(ns main
(:require [lib :as lib]))
(defn doit []
(println lib/a))
lib.cljs
(ns lib)
(def a 2)
And I can do this:
cljs.user=> (require '[main :as main])
WARNING: main is a single segment namespace at line 2 main.cljs
WARNING: lib is a single segment namespace at line 2 lib.cljs
nil
cljs.user=> (main/doit)
1
nil
Then I update lib.cljs
and reload it:
cljs.user=> (require '[lib :as lib] :reload)
WARNING: lib is a single segment namespace at line 2 lib.cljs
nil
cljs.user=> (main/doit)
2
nil
So it looks not hard to watch and get the changed path, then there are expressions left in the repl.
If we can connect to the same process(the REPL) and send a piece of code, it would work. And that watcher don't even need to be written in ClojureScript.
Do you think TCP Socket REPL is capable of doing this?
This kind of intrigued me so I wrote a very naive, but functional enough to show, method of doing this in lumo using the socket REPL. It basically works as inf-clojure-eval-buffer
would, sending the changed file contents to the socket REPL for evaluation.
https://github.com/jmfirth/lumo-watch/blob/master/watch.cljs
About halfway through implementation it was working in some capacity and it was very interesting/weird developing this with itself once initially evaluated. I'm not sure if I intend to try and take this any further, but it was a fun diversion this morning.
@jmfirth looks interesting. I'm not familiar with Socket REPL, do you see any guide out there?
For the watcher I would recommend https://github.com/shama/gaze for performance.
Seems in your code namespaces are not handled manually, does it reload?
I got a experimental version. I tried but it appears to be buggy. https://github.com/Cumulo/cumulo-workflow/blob/master/server/polyfill/workflow_server/watcher.cljs
Thanks to guide from @pesterhazy , I figured out how to use socket REPL in this case.
In short, it's as simple as sending TCP requests:
(def net (js/require "net"))
(def client (.createConnection net (clj->js {:port 6000})))
(.on client "data" (fn [chunk]
(.log js/console (.toString chunk))))
; in real programs, need to make sure connection open first
(.write client (str "(require '" ns-path " :reload)" \newline))
(.write client "(require '[workflow-server.main :as main])\n")
(.write client "(main/on-jsload!)\n")
My entire demo is in https://github.com/Cumulo/cumulo-workflow/blob/master/server/tasks/watcher.cljs
It's OK for me to use an external script to do it. Closing...
Since lumo now utilizes Node.js API, we may do more than Planck. One things I tried but felt clumsy is that I want to write small Node.js apps in ClojureScript so I tried fighweel. But it requires quite some code to config figwheel, what's more, when I'm migrated to Boot, it's even more configs.
How about such a feature in lumo? Like detect file changes, and reload namespaces, and call a
on-jsload
function. It's like we do(require 'x.y :reload)
(x.core/on-jsload)
manually but now we do it with lumo.I guess anyway we have to compile ClojureScript in
:advanced
mode to make performant. No mention to use it in production.