Hi, I'm having some problems with encoding over a websocket. A small amount of users get encoding errors. What I get
Received unreadable data ' #object[G [:client/pong #object[h {:time 1599227731033}]]] ', for client: nil #error { :cause No reader function for tag object
Do any of you know what type of object '#object[G' can be? Is it on the browser side or on the server side it somehow get wrapped?Hello Clojurians, I am a noob and trying to figure out how to develop a full stack app using shadows-cljs. The default index.html seems to kick off the JS code, but how do you run the back-end server? Should the backend run through shadow-cljs or should it run through a completely independent instance of REPL?
Is it possible to alias to a macro. (def my-var ns.macro-file/my-macro)
@timofey.sitnikov I recommend keeping your backend entirely separately and just have it serve the HTML and the static files shadow-cljs produced. shadow-cljs does not provide anything to do backend development.
@grounded_sage not in CLJS, you can with some trickery via CLJ
@thheller, OK, so, I need two instances of terminal, one for CLJS and the other for for backend. What I am having a hard time with is shadow-cljs relies on index.html
file in the public directory, but it seems like the backend should serve the index.html as well as provide the backend api.
@thheller okay. Cljs is the particular one I was getting at. Was trying to see if it possible to avoid file duplication just to get at one or two macros. It is definitely possible doing :#?(:cljs (:require-macros [self-required.ns :refer [my-cljs-macro] :rename {my-cljs-macro normal-macro-name}])
for the current ns and also doing :require .. :refer .. :rename ..
in outside files. Though my preference is to avoid the rename
leaking into the public API from that ns. So I currently have the duplicated files with their minor variations of macros and am considering the auto-namespace aliasing if it makes sense to do so.
shadow-cljs does not rely on the index.html
, you just need some HTML to instruct the browser to load the JS and so on. just have your backend server either generate the HTML or serve the file.
whenever I want macros from other namespaces to become part of an API I just create another macro either just directly calls that macro or emits code with the renamed symbol, eg. https://github.com/thheller/shadow-experiments/blob/master/src/main/shadow/experiments/grove.clj
I may be missing how to tell shadow-cljs
not to spin up its own http server. I already started the backend server, but when I start shadow-cljs
, I get the TCP port in use warning, and it still spins up another http server.
[I] /home/sporty/clojure/bubbleuptop~> shadow-cljs watch app
shadow-cljs - config: /home/sporty/clojure/bubbleuptop/shadow-cljs.edn
[2020-09-07 09:17:33.474 - WARNING] TCP Port 8080 in use.
shadow-cljs - HTTP server available at <http://localhost:8081>
shadow-cljs - server version: 2.10.15 running at <http://localhost:9630>
shadow-cljs - nREPL server started on port 40611
shadow-cljs - watching build :app
[:app] Configuring build.
[:app] Compiling ...
Warning: Nashorn engine is planned to be removed from a future JDK release
[:app] Build completed. (6197 files, 0 compiled, 0 warnings, 22.65s)
quite often do this for plain functions too. just one function calling another, no need to make it more complicated than that IMHO
you configured that server in shadow-cljs.edn
either :dev-http
or :devtools {:http-port ...}
. just remove them if you don't intend to use them.
also yikes 6197 files
π
This makes me want to cry π, this is so simple, but coming into this so not obvious from system point of view. Thank you for helping, I would have banged my head agains the wall.
Huh? what do you mean, what does it tell you?
that is a lot of files π likely including a lot of npm files which you may want to look into at some point. your output is likely gigantic.
The problem I have there is that the macro I have is from a .cljc
namespace. So the preferred name is already declared in that ns when it is ran through the clj
compilation step to generate the macro. That is why I was thinking I could possibly have two variations of the macro with -cljs
appended to the name for the cljs version and then rename it to remove the -cljs
or redeclare the name after the clj macro to the same name but inside #?(:cljs β¦)
I don't quite understand what you are trying to do here? just have the macro detect whether its supposed to generate CLJ or CLJS code?
There is multiple macros being layered on. The (:ns &env)
doesnβt appear to work with this happening.
This is where the macro layers start.
https://github.com/replikativ/hitchhiker-tree/blob/master/src/hitchhiker/tree/utils/async.cljc#L10
I resolved this issue by duplicating the files and just having the if-async?
set to true for the cljs
version.
https://github.com/groundedSAGE/hitchhiker-tree/tree/update-cljs-support/src/hitchhiker/tree/utils
(def ^:dynamic *async?*
#?(:clj false :cljs true))
this is always :clj
and thus true
as far as the macro is concernedSo I just duplicated those files and had them false
and true
in their respective clojure
cljs
namespaces
what you are saying does not make sense to me
(defmacro if-async?
""
{:style/indent 2}
[then else]
(if (is-cljs? &env)
then
else))
Well the *async?*
is always in clj
when being evaluated in the macros.
just have the macro figure out what its supposed to do when it is called
you cannot determine this anywhere else
I had this before but it did not seem to work. https://github.com/groundedSAGE/hitchhiker-tree/blob/f6a4080c3f60c6755c583a5cd12658c013b14c38/src/hitchhiker/tree/utils/async.cljc#L12
looks fine
the version below however does not
(defmacro go-try
"Asynchronously executes the body in a go block. Returns a channel
which will receive the result of the body when completed or the
exception if an exception is thrown. You are responsible to take
this exception and deal with it! This means you need to take the
result from the channel at some point."
{:style/indent 1}
[& body]
(if-async?
(let [e (if (:ns &env) 'js/Error Throwable)]
`(async/go
(try
(do ~@body)
(catch ~e e# e#))))
`(do ~@body)))
the if-async?
is expanded when the macro is loaded in CLJ, thus it takes the CLJ branch and is not async
macros can be confusing like that π
Yea thatβs what was happening. The macroexpansion happening in CLJ basically cascades through when it is used in other macros
(defmacro go-try
"Asynchronously executes the body in a go block. Returns a channel
which will receive the result of the body when completed or the
exception if an exception is thrown. You are responsible to take
this exception and deal with it! This means you need to take the
result from the channel at some point."
{:style/indent 1}
[& body]
(if (async? &env)
(let [e (if (:ns &env) 'js/Error Throwable)]
`(async/go
(try
(do ~@body)
(catch ~e e# e#))))
`(do ~@body)))
always check against the env when doing this kind of stuff
honestly I think what you are trying to do there is doomed to fail. you cannot just "add async" as if it didn't change the entire semantics of the entire code infecting everything
might as well start from scratch with a better setup π
Well it now works just not as elegant as I thought I could make it. There is code that makes the necessary parts sync when needed. Iβm still relatively new to the project so I am yet to have a comprehensive overview of how all the pieces fit together.
What's the current best way to interopt with AsyncIterators
? I have bytes coming in via a callback but the msgpack library I am using wants to consume bytes asynchronously via stream: AsyncIterator<Uint8Array>
. Right now I have my callback just putting the incoming bytes onto a channel, but I'm not sure the best way to pipe that channel into an async iterator.
Hi everybody!, Does anybody knows why this macro
(defmacro tester [form]
(println (macroexpand form))
nil)
When used from clojure :
(tester (let [a 5] a))
;; prints
(let* [a 5] a)
But when used from clojurescript :
(tester (let [a 5] a))
;; prints
(let [a 5] a)
So the same macro doesn't do the same, macroexpand doesn't work at macro level when the cljs compiler calls it