Fork me on GitHub
#shadow-cljs
<
2019-10-02
>
Abhinav Sharma08:10:15

Hello everyone, Background I have a question regarding the way shadow-cljs handles browser connections - I experimented with connection an app to chromium and firefox, the chromium app was the one running, when I did (shadow/repl :main) and later I opened the same localhost in the firefox one. Curiosity I was wondering whether there’s a way to inspect the network calls in both browsers. From my initial experimentation it seems that the level of integration is definitely tighter with the first browser where I connected with (shadow/repl :main). I read the shadow-cljs user guide but couldn’t find any config as such - please let me know if it’s possible or not.

thheller08:10:39

not really sure what you are asking. the REPL only ever talks to one browser (typically the first one connected).

Abhinav Sharma13:10:19

Hi @U05224H0W, That is what I concluded as well, I was just curious whether it was possible to replicate the same session in two browsers or not.

thheller13:10:01

no it is not. too many things that could go wrong if they connect at different times and miss a command or so

Abhinav Sharma14:10:40

Hmm, interesting. Thanks for the clarification @U05224H0W 👍

thheller09:10:32

so if you triggered the request from the REPL then only one browser will do that request

lilactown18:10:14

I’m getting an error when trying to use a goog JS namespace again:

Uncaught ReferenceError: $jscomp is not defined
    at statsBar (stats_bar.js:13)
    at Constructor.eval (d3.cljs:25)
    at Constructor.reagent$impl$component$custom_wrapper_$_componentDidMount (component.cljs:189)
    ...

lilactown18:10:12

The offending file

lilactown18:10:42

the stacktrace is pointing at line 13 where it refers to getRequiredKey

thheller18:10:02

uhm thats not how you write goog namespaces. please write plain ES6 instead.

thheller18:10:22

polyfills probably aren't injected properly if you write ES6 code this way

thheller18:10:48

ie. it fails because of how GCC rewrote const [width, height] ... (probably)

thheller18:10:37

or just set :output-feature-set :es6 or up so it doesn't rewrite those at all

thheller18:10:43

then it doesn't require polyfills

lilactown18:10:35

I’ll give that a shot

lilactown18:10:59

moving this from lein-figwheel. I think it had the output set to es6 and I probably didn’t do the same in my shadow config

thheller18:10:17

CLJS or figwheel won't process those files at all in dev

thheller18:10:25

so you likely just lived without polyfills

thheller18:10:50

but be careful if you write the files like that

thheller18:10:06

since statsBar and getRequiredKey will actually be global functions

thheller18:10:20

they aren't namespaced so would conflict with any other code

thheller18:10:33

(if you have others declaring var or so)

lilactown18:10:57

I’ll make a note

lilactown18:10:12

not code I wrote, will probably migrate to CLJS at some point

thheller18:10:33

I'm not entirely sure why the $jscomp polyfills are missing though. they should be added

lilactown18:10:20

maybe an ordering issue?

lilactown18:10:35

but it isn’t executing until I switch to the screen with the graphs, so that doesn’t make sense to me

thheller18:10:06

well it would only happen if the statsBar function is called

lilactown18:10:40

hmm, I’m still getting the same error after changing compiler options

lilactown18:10:01

{:target :browser
                :modules {:main {:entries [amperity.web.dev
                                           amperity.web.prod]}}
                :output-dir "resources/public/js/compiled/"
                :asset-path "js/compiled/"
                :compiler-options {:language-in :es6
                                   :output-feature-set :es6
                                   :devcards true}
                :dev {:closure-defines {"re_frame.trace.trace_enabled_QMARK_" true
                                        "day8.re_frame.tracing.trace_enabled_QMARK_" true}}
                :preloads [day8.re-frame-10x.preload
                           devtools.preload]
                :external-config {:devtools/config {:features-to-install
                                                    [:formatters :hints :async]}}}

lilactown18:10:03

statsBar is still getting compiled to: var $jscomp$destructuring$var0 = $jscomp.makeIterator(getRequiredKey(options, "dimensions"));

lilactown19:10:33

clearing out my build cache fixed it #sorrynotsorry

thheller09:10:54

should be fixed in future releases

thheller19:10:12

oh yeah the cache might not be invalidated properly for those files

thheller19:10:33

it kinda presumes that the only closure JS files are from the closure library which won't change 😛

isak21:10:13

Is it possible to access state gathered via compilation (e.g., a macro that writes to an atom) right before the build finishes and the information is (possibly) discarded?

lilactown21:10:31

@isak are you talking about during when you have a watch running, or during a release build?

isak21:10:52

@lilactown this is during a release build

lilactown22:10:59

I’m not sure

lilactown22:10:08

what are you trying to do exactly?

isak22:10:35

@lilactown I'd like to make a translation function/macro that automatically makes the texts/text-ids available for translation (by upserting them to a database)

isak22:10:33

Similar to this library for elixir: https://github.com/elixir-gettext/gettext

lilactown22:10:27

first knee-jerk hacky way would be to write to a file during macro time and then after compilation, have a script that does the upsert

lilactown22:10:01

but doing effects during macro time is rife with potential problems

isak23:10:34

@lilactown interesting. Do you know what kind of issues may arise? Another way that could work is to walk the AST if shadow provides one in a build hook. ( I think I remember seeing something about this )

lilactown23:10:06

mainly during dev time when you’re watching the app, macros happen right after read time so e.g. they’ll get run on every incremental compilation of that file

lilactown23:10:32

but also the order in which files get compiled isn’t guaranteed deterministic, so if you depend on ordering you might be in trouble

lilactown23:10:16

shadow also doesn’t recompile everything in the dependency graph in one go, so if your dependent namespaces also have side effects that need to be run all at once, you’re in trouble

lilactown23:10:48

(last one again talking about during dev time while watching the file system)

isak23:10:54

Ok, I was thinking I'd just make the macro pass-through to a function in development, so it sounds like the file-appending strategy would work

lilactown23:10:59

I'd be pretty interested to know of a good solution for i18n / localization in first class cljs. If you figure out how to do it well and can share it, I'd greatly appreciate it

isak23:10:09

Will do, thanks for the help

thheller08:10:44

@isak I started some proof of concept regarding i18n a while ago but never had a real need to finish it https://github.com/thheller/cljs-i18n-api

thheller08:10:02

the idea was exactly to collect all strings in the metadata and then extract it later via :build-hooks

isak14:10:41

@U05224H0W oh nice! I will try to build on this.

thheller14:10:44

it will store the things in the the analyzer data for the namespace

thheller14:10:53

that will ensure that it works properly with caching and so on

thheller14:10:12

don't store it globally. it must be per ns and combined after the build if needed

thheller14:10:18

otherwise it won't work with caching enabled

isak14:10:20

right. And this same `*compiler* will be available in a build hook?

isak14:10:39

good to know, thanks

thheller14:10:03

no build hooks have direct access to the full shadow-cljs build-state

thheller14:10:02

so you'll find the data in (get-in build-state [:compiler-env :cljs.analyzer/namespaces 'the.ns :your/key])

isak14:10:32

got it, thanks 🙂

thheller14:10:59

remember to use namespaced keys for your data to avoid interfering with the normal compile data

cjsauer23:10:08

I realize this is likely not its use-case, but for toy examples it’s convenient to use :dev-http {8000 {:handler }} as a cheap way to test out client-server interactions. However, when eval’ing server functions, I’m finding that they aren’t picked up until I “bump” the shadow-cljs.edn file, causing shadow to restart the server. Is there a better way to reload server changes?

thheller08:10:13

you can use the CLJ REPL to reload CLJ code

cjsauer00:10:59

I have a Clojure REPL using cider-connect-sibling-clj in emacs, would that have the http server in-process? After reloading the ns with my handler in it, subsequent HTTP requests from the cljs app don’t appear to invoke the newly eval’d code.

cjsauer00:10:23

Might be a question for #cider

tony.kay23:10:04

I’m trying out react native support…seeing this:

Exception in thread "async-dispatch-5" java.lang.RuntimeException: java.lang.Exception: Not supported: class cljs.tagged_literals.JSValue
        at com.cognitect.transit.impl.WriterFactory$1.write(WriterFactory.java:65)
        at cognitect.transit$write.invokeStatic(transit.clj:167)
        at cognitect.transit$write.invoke(transit.clj:164)
        at shadow.cljs.devtools.server.common$fn__15653$fn__15654.invoke(common.clj:59)
        at clojure.core$map$fn__5862$fn__5863.invoke(core.clj:2742)
        at clojure.core.async.impl.channels$chan$fn__1714.invoke(channels.clj:300)
        at clojure.core.async.impl.channels.ManyToManyChannel.put_BANG_(channels.clj:83)
        at clojure.core.async.impl.ioc_macros$put_BANG_.invokeStatic(ioc_macros.clj:992)
        at clojure.core.async.impl.ioc_macros$put_BANG_.invoke(ioc_macros.clj:991)
        at shadow.cljs.devtools.server.web.api$eval36151$fn__36154$fn__36208$state_machine__6737__auto____36227$fn__36229.invoke(api.clj:82)
and so forth. Seems to happen during the flush stage…UI says:
Compiling ...
Flush: cljs/core.cljs