Fork me on GitHub
#boot
<
2015-12-09
>
naomarik07:12:24

ah that's me simple_smile

jannis13:12:46

With boot-cljs, is there a way to pass environment variables from a boot task to one of the :init-fns or to ClojureScript in general?

jannis13:12:12

If there isn't, I can probably work around it by generating a cljs config file via a custom task on the fly, just before cljs. If anyone has a better idea, I'd be happy to hear it simple_smile

micha13:12:53

that's what i use for that purpose

micha13:12:15

i like configuring my applications via environment variables, too

jannis13:12:19

@micha: Looks interesting. How are you using it from boot?

micha13:12:22

@naomarik: thanks for taking the time to document that!

micha13:12:39

@jannis: i just do like

micha13:12:15

well for a web app, for instance, i'm making single page apps

micha13:12:40

so everything is clientside

micha13:12:57

but the client talks to a webservice to get data from the database

micha13:12:16

but i have a few different environments the client is deployed to

micha13:12:27

like local dev, staging in the cloud, and production

micha13:12:42

i have an env var with the URL of the backend webservice to use

micha13:12:59

i can do like:

naomarik13:12:04

@micha np! I've spoke to the CIDER dev and submitted a PR to show complete end to end from config to browser repl

jannis13:12:15

Yeah, similar here. My app spawns two services, one serving the backend, the other serving the client. I'd like to be able to pass in the ports both server from via boot, so e.g. the client knows which port use in order to talk to the backend.

micha13:12:42

@naomarik: did you see the boot wiki? perhaps you could add your config to the cider howto there?

naomarik13:12:54

it was way easier getting started with boot and seems faster than lein, and i honestly have an insanely superficial understanding of both just starting on all this yesterday

micha13:12:03

@jannis: so i do something like this in my build.boot:

naomarik13:12:38

@micha you guys have most of the instructions ready and done here https://github.com/adzerk-oss/boot-cljs-repl

micha13:12:44

(env/def
  BACKEND_URL "")

naomarik13:12:49

the only other thing i had to do was my boot profile

naomarik13:12:26

and tenzing wasn't very helpful giving me 5 old dependencies (that i had no idea were old)

micha13:12:27

@jannis: that expression defines the var BACKEND_URL, with the default given

jannis13:12:44

@micha: Right, so you do that outside your tasks and then you have access to BACKEND_URL from all Clojure and ClojureScript sources?

micha13:12:56

@jannis: exactly

jannis13:12:58

Via (env/def BACKEND_URL)

micha13:12:21

and you can make them :required and it will throw an exception with the name of the thing that wasn't configured

micha13:12:29

which is crucial for maintaining sanity simple_smile

jannis14:12:07

Ok, I'll give that a shot. Thanks! simple_smile

micha14:12:10

so then when i deploy to any kind of application container in the cloud i can set env vars on the environment

micha14:12:32

the basic concept is to try to store environment-specific configuration in the environment itself, not in a big map in a config file

micha14:12:29

doing it that way automatically avoids all the issues of sensitive info being in config files , etc

micha14:12:38

one warning though: be careful if you use (env/env) in cljs

micha14:12:46

like to get all env vars as a map

micha14:12:59

because it will compile your whole environment into the js file

micha14:12:06

which is almost certainly bad

micha14:12:18

because it will probably contain something sensitive

micha14:12:35

instead just use (env/def ...) in cljs

micha14:12:39

i need to update that library to print a warning in that case

jannis14:12:23

Good point, leaking the deployment env into the client would be pretty bad

micha14:12:06

(env/def FOO nil) is ok, but (get (env/env) "FOO") would leak your whole env

jannis14:12:39

Oh, what if I build the whole project into an uberjar for deployment and run it with java -jar <uberjar>? Where would I define env vars then? Not in build.boot I guess because that's not part of the jar.

micha14:12:55

you'd define it in the environment!

micha14:12:06

like whatever machine is running your uberjar

micha14:12:11

would have those env vars set

jannis14:12:31

Sure. I'm not sure how those vars would then make it into the ClojureScript side.

micha14:12:40

oh the cljs side is different

micha14:12:52

because that's just compiled into static js and whatnet

micha14:12:15

the frontend is configured when you compile it

micha14:12:24

like in my example

micha14:12:47

i need to compile the frontend with config for talking to a specific backend url

micha14:12:56

then i push that to s3

jannis14:12:22

Yep, that's what I was wondering about. Ok, makes sense.

micha14:12:22

it would be nice if s3 could somehow provide env vars

micha14:12:04

i haven't yet figured out what the equivalent of env vars is for static html

micha14:12:12

i bet there is something

micha14:12:43

maybe a file in a standard location, like robots.txt

micha14:12:48

or something

micha14:12:14

it would be optimal to have a file on s3 with the vars in it

micha14:12:29

and anything i push to that bucket would get its config from that

micha14:12:42

well maybe not optimal

jannis14:12:25

@micha: Hm. If I do SERVER_URL=<something> boot run-development, and print (env/env) in ClojureScript, I can see SERVER_URL. However, if I do (env/def SERVER_URL :required), it's nil.

micha14:12:14

you're sure?

micha14:12:24

try like SERVER_URL=asdf boot repl

jannis14:12:52

(println (get (aenv/env) "SERVER_URL")) prints the URL, so it's set (note I'm passing a string to get).

micha14:12:56

aenv/def doesn't return a string

micha14:12:07

it defines a var, which doesn't really exist in cljs world

micha14:12:15

a better test would be

micha14:12:43

(aenv/def SERVER_URL :required)
(prn SERVER_URL)

micha14:12:12

cljs doesn't have vars

micha14:12:31

in clojure that would work because vars evaluate to deref

jannis14:12:37

That's it. I thought def would return the value/s as well

jannis14:12:50

It works with the "better test" simple_smile

jannis14:12:31

Good stuff

naomarik15:12:04

where should I check if my DOM is getting wiped on code reloads and giving me Target container is not a DOM element.

naomarik15:12:52

it was my browser history navigation hook

jaen15:12:39

What do you use?

naomarik15:12:12

`(defn hook-browser-navigation! [] (doto (History.) (events/listen EventType/NAVIGATE (fn [event] (secretary/dispatch! (.-token event)))) (.setEnabled true))) ` using this code block that came from my luminus project simple_smile

naomarik15:12:48

i moved (hook-browser-navigation!) outside the init function that boot-reload uses

naomarik15:12:50

and it seems to work

jaen15:12:03

I'm not sure that's the best idea

jaen15:12:07

I mean, what are you using for your UI?

jaen15:12:10

Regent? Om?

jaen15:12:19

And how do you initialise it?

naomarik15:12:42

reload {:on-jsload 'boot-app.app/init}

jaen15:12:53

and inside that?

naomarik15:12:54

as an option in my build.boot

naomarik15:12:02

(defn init [] (mount-components))

naomarik15:12:11

it was this...

naomarik15:12:11

(defn init [] (hook-browser-navigation!) (mount-components))

naomarik15:12:15

and that was breaking the dom

naomarik15:12:36

any code save would remove the whole dom

naomarik15:12:06

so i pulled it out of the init function

naomarik15:12:12

and history is working fine...

naomarik15:12:20

i'm not sure why it would break, figwheel was working fine with it

jaen15:12:16

But how does (mount-components) look?

naomarik15:12:37

(defn mount-components []
  (reagent/render [#'page] (.getElementById js/document "wrapper")))

naomarik15:12:59

i don't have any components with that ID

jaen15:12:07

Hmm, that doesn't look too bad. I though you were maybe mounting on the document itself

jaen15:12:14

And that was killing the dom

jaen15:12:24

Also you don't need to do [#'page]

jaen15:12:30

just [page] is enough.

naomarik15:12:44

wonder why it came like that

jaen15:12:05

But yeah, you should do things like that once

jaen15:12:08

For example

jaen15:12:38

(defn app-init! []
  (install-devtools!)
  (log/debug "starting app")
  (mount-root!)
  (history/setup-history! (.-body js/document)))

(defn app-reload! []
  (log/debug "reloading app")
  (mount-root!))

jaen15:12:45

I have something like that

jaen15:12:29

with app-init! specified in your cljs.edn` file

jaen15:12:01

{:require [presentation.frontend.core]
 :init-fns [presentation.frontend.core/app-init!]
 :compiler-options {:main         "presentation.frontend.core"
                    :asset-path   "/assets/javascripts/application.out"}}

jaen15:12:18

And for reload you use only the app-reload! one

jaen15:12:20

(br/reload :ip "0.0.0.0" :ws-host "himitsu" :on-jsload 'presentation.frontend.core/app-reload!)

naomarik15:12:02

working perfectly @jaen

jaen15:12:22

So you separate things you want to redo each time (like remounting React components) from things you want to just once (likes setting cljs devtools or configuring timbre).

jaen15:12:18

PS for multiline blocks of code you can use three backticks - `

naomarik15:12:46

yeah figured that out on last one simple_smile

naomarik15:12:24

any sites you've made jaen?

naomarik15:12:28

that i can see? simple_smile

jaen15:12:33

Though I'm curious why hook-browser-navigation! complained in the first place. You forgot to specify a DOM node to listen?

jaen15:12:18

That are online? Not really. The only thing I've done that is on-line is http://pinshape.com, but that's in Ruby and it has changed a lot since I've jumpstarted it.

naomarik15:12:31

i need to specify a dom for event/listen?

jaen15:12:31

And I'm not sure you would want to see my Clojure code anyway, it's not so nice.

jaen15:12:36

I think so.

naomarik15:12:37

i don't think so, my naive understanding is that it registers an event for NAVIGATE then calls secretary functions

jaen15:12:46

As you see it's dom node, then event type, then handler.

naomarik15:12:07

yeah you're setting up a listener on keydown there

jaen15:12:33

Yeah, but navigate events need to fire on something

naomarik15:12:58

(events/listen
          EventType/NAVIGATE
this block listens to probably window navigate event

naomarik15:12:51

no need for dom node cause it's not listening on the dom in this case simple_smile

jaen15:12:31

Well, the official google docs I've sent

jaen15:12:33

Don't seem to agree

jaen15:12:43

It doesn't say that src parameter is optional.

jaen15:12:38

I'm dumb, sorry xD

jaen15:12:52

Didn't notice the doto : V

jaen15:12:15

So you're doing it right

jaen15:12:58

The History element is passed as the first argument with the doto macro.

jaen15:12:34

So everything should be all right '

pandeiro18:12:21

Does anyone remember when Github finally started showing build.boot files as clojure?

pandeiro18:12:41

Just want to know for reference; I'm trying to get Gitlab to do the same

jaen19:12:51

I don't remember for Github, but it would be awesome for Gitlab to do that.

pandeiro19:12:29

I remember Github took a while, I remember Alan opened an issue, it got a little testy, etc etc