Fork me on GitHub
#shadow-cljs
<
2020-12-26
>
GGfpc14:12:23

Hello! Is there anyway I can set up an environment variable that is replaced at build time? For instance, I want my source code to have an IP address pointing to localhost, but when I release a build I want it to be replaced with my server's address

oconn14:12:38

I use closure-defines for this kind of configuration. https://clojurescript.org/reference/compiler-options#closure-defines & goog-define https://cljs.github.io/api/cljs.core/goog-define where the second argument would be your default localhost address

codonnell14:12:14

☝️ Same. There's a section on how to use them in the user guide, too: https://shadow-cljs.github.io/docs/UsersGuide.html#closure-defines.

GGfpc15:12:09

that's perfect, thanks!

David Pham15:12:51

I use deps.edn and aliases with a namespace containing a map with all the variables.

oconn15:12:38

Hi, I’m looking to use shadow-cljs to self-host a cljs project in a web worker. I feel like I’m close and probably configuring my build wrong… In my shadow-cljs.edn config I have my cljs worker build configured like this;

{:builds {:cljs-worker {:target :browser
                        :output-dir "resources/public/js"
                        :asset-path "/js"
                        :compiler-options {:optimizations :simple}
                        :modules {:cljs-worker-base {:entries [shadow.cljs.bootstrap.env]}
                                  :cljs-worker {:init-fn workers.cljs.core/init!
                                                :depends-on #{:cljs-worker-base}
                                                :web-worker true}}}
In workers.cljs.core i’ve got;
(ns workers.cljs.core
  (:require [cljs.env :as env]
            [cljs.js :as cljs]
            [shadow.cljs.bootstrap.browser :as boot]))

(defn- process-response
  [{:keys [error value] :as result}]

  (when (some? error)
    (js/console.log "ERROR")
    (js/console.error error))

  (when (some? value)
    (js/console.log "VALUE")
    (js/console.log value))

  result)

(defonce compile-state-ref (env/default-compiler-env))

(defn evaluate [code]
  (cljs/eval-str
   compile-state-ref
   code
   nil
   {:eval cljs/js-eval
    :load (partial boot/load compile-state-ref)}
   process-response))

(defn init! []
  (boot/init compile-state-ref {:path "/js"} #(evaluate "(+ 1 1)")))
which was inspired by https://code.thheller.com/blog/shadow-cljs/2017/10/14/bootstrap-support.html - Configured this way results in the following error; failed to download boostrap file:/js/index.transit.json It seems this file is only generated when setting the target to bootstrap? Changing my config to more closely match the blog post generates index.transit.json but does not build modules.
:cljs-worker
  {:target :bootstrap
   :output-dir "resources/public/js"
   :asset-path "/js"
   :compiler-options {:optimizations :simple}
   :modules {:cljs-worker-base {:entries [shadow.cljs.bootstrap.env]}
             :cljs-worker {:entries [cljs.js]
                           :exclude #{cljs.js}
                           :macros []
                           :init-fn workers.cljs.core/init!
                           :depends-on #{:cljs-worker-base}
                           :web-worker true}}}
Is there a configuration that will allow me to build a worker supporting self-hosted cljs?

thheller17:12:08

@oconn failed to download boostrap file:/js/index.transit.json looks like you are trying to do this directly from the filesystem? that won't work, you need a http server. you can use :dev-http

thheller17:12:26

:modules does nothing in :bootstrap

thheller17:12:57

you need the browser build and the bootstrap build. separate.

oconn19:12:15

@thheller - Looks like index.transit.json is loaded directly in shadow.cljs.bootstrap.browser/init. I’m running a dev server using;

:devtools {:http-root "resources/public"
           :http-port 9000
           :preloads [shadow.remote.runtime.cljs.browser]} 
I changed my bootstrap build to
:cljs-worker
  {:target :bootstrap
   :output-dir "resources/public/js/workers/cljs"
   :compiler-options {:optimizations :simple}
   :entries [cljs.js workers.cljs.core]
   :exclude #{cljs.js}
   :macros []}
and that is compiling everything under the output-dir but I’m not sure what js file I’m supposed to load into my web worker? Taking a looking at the bootstrap-support build in shadow-cljs ’s shadow-cljs.edn config, it outputs to out/demo-selfhost/public/bootstrap. The index file in that dir loads <script src="/worker/js/base.js"></script> - Is there supposed to be a base.js file in the output?

deplect19:12:05

I am running into something interesting, I have to access the :cause field of an cljs.core/ExceptionInfo and noticed it's being mangled by an release build. Now figuring out how to protect against the mangling.

deplect20:12:30

The cause I want to read out is build here in this async.interop. Advanced compilation mangles the class name, and the cause field, making it inaccessible for ex-cause.

thheller20:12:29

@oconn no. your :modules control that in your case will be cljs-worker.js in the :output-dir

oconn15:12:51

@thheller Thanks for pointing me in the right direction! I was loading my web worker using a relative path. Also didn’t know I needed two separate builds for self-hosted cljs. Thanks again!

thheller20:12:38

you load that in the html and then bootstrap init

thheller20:12:17

again failed to download boostrap file:/js/index.transit.json this error suggests that you just loaded the index.html directly from the filesystem in the browser instead of

thheller20:12:20

@deplect in general if something gets mangled that you don't want mangled you need externs. see https://shadow-cljs.github.io/docs/UsersGuide.html#_simplified_externs just add cause one line to preserve it

deplect20:12:40

@thheller amazing, was just writing my own extern, but this is magic. Thank you