Fork me on GitHub
#shadow-cljs
<
2018-03-28
>
thheller08:03:05

closure v20180319 is now available on maven. will bump shadow-cljs later.

hlolli09:03:13

@thheller sleepelss night for me, I tried the new closure. Was hopeing it would fix a Quill bug I had completly randomly, evening before launching a new webapp. So two post-compilation bugs I'm gettiing. But as these are both admin endpoints, then I'm actually running shadow-cljs watch in production. Somehow build with optimizatioon :none gave me an error, wait I can send it...

hlolli09:03:55

shadow-cljs release :admin  ~/Documents/visitor
shadow-cljs - config: /home/hlolli/Documents/visitor/shadow-cljs.edn version: 2.2.20
shadow-cljs - connected to server
[:admin] Compiling ...
optimizations set to :none, can't optimize
{}
ExceptionInfo: optimizations set to :none, can't optimize
	clojure.core/ex-info (core.clj:4739)
	clojure.core/ex-info (core.clj:4739)
	shadow.build.closure/optimize (closure.clj:1081)
	shadow.build.closure/optimize (closure.clj:1074)
	shadow.build.api/optimize (api.clj:182)
	shadow.build.api/optimize (api.clj:176)
	shadow.build/optimize (build.clj:318)
	shadow.build/optimize (build.clj:310)

thheller09:03:40

yeah :none is not an optmization setting .. its literally just compile

hlolli09:03:01

nice, I guess that omits the devtools?

thheller09:03:54

but that doesn't affect the optimizations used for JS at all

thheller09:03:14

you can set :js-options {:optimizations :whitespace} to switch it from :simple

thheller09:03:34

but can you say more about the quill thing? does it still not work with the latest closure?

hlolli09:03:46

nope, I'll send the code which fails, it's react-quill actually

hlolli09:03:46

(:require ["react-quill" :as Quill])

(defn component []
  (let [quill-ref (atom nil)]
    (r/create-class
     {:reagent-render
      (fn [] [:> Quill {:default-value ""
                        :ref (fn [el] (reset! quill-ref el))
                        :modules {:toolbar {:container [[{:header [1 2 3 4 5 false]}]
                                                        ["bold" "italic" "underline" "strike" "blockquote"]
                                                        [{:list "ordered"} {:list "bullet"} {:indent "-1"} {:indent "+1"}]
                                                        ["link" "image"]
                                                        ["clean"]]
                                            :handlers  {:image (fn [_] 
                                                                 (let [editor (.getEditor @quill-ref)
                                                                       selection (.getSelection editor)]
                                                                   (.insertEmbed editor
                                                                                 selection.index "image"
                                                                                 (js/window.prompt "Please provide an image url")
                                                                                 "user")))}}}}])})))
headily elided, when clicking the image logo on the editor to provide img url, will work in :non the error otherwise is
admin.cljs:429 Uncaught TypeError: b.fi is not a function
    at b.<anonymous> (admin.cljs:429)
    at HTMLButtonElement.<anonymous> (quill.js:9393)
(anonymous) @ admin.cljs:429
(anonymous) @ quill.js:9393
For line number comparison then I'm running Quill Editor v1.3.6 one minor version above that which is declared in react-quill, same behaviour is in v1.3.5.

hlolli09:03:58

so line 423 in admin.cljs is .inserEmbed editor

hlolli09:03:41

com.google.javascript/closure-compiler-unshaded "v20180319" the closure version

thheller09:03:07

is that error with watch? or release only?

hlolli09:03:58

release only

thheller09:03:56

did you try shadow-cljs release the-build --debug?

thheller09:03:18

should give a better clue what b.fi is.

thheller09:03:26

do you have :infer-externs :auto?

hlolli09:03:51

I'm running now --debug, didn't touch the :infer-extern option

thheller09:03:00

just trying to rule out that it is not a problem on the CLJS side.

thheller09:03:17

definitely always turn on :compiler-options {:infer-externs :auto} if you run into any issues

hlolli09:03:02

ok I try that, --debug only gave me warnings about transit and nashorn

thheller09:03:35

runtime error should be better though

hlolli09:03:56

boom, it spotted something shade there now

431 |                                                                     (.insertEmbed editor
---------------------------------------------------------------------------^----
 Cannot infer target type in expression (. editor insertEmbed selection.index "image" (js/window.prompt "Hvað er URL á myndina?") "user")
excuse the foreign language used there 🙂

thheller09:03:20

I think all you'll need is ^js editor (.getEditor @quill-ref)

thheller09:03:36

yeah exactly

thheller09:03:54

you need to tell the compiler that editor is a JS object and nothing that uses it should be renamed

hlolli09:03:16

better later than never, to learn

hlolli09:03:31

so carrot js is a shadow reader?

hlolli09:03:49

never seen this before

thheller09:03:54

you mean ^js?

hlolli09:03:28

yes, well it fixed it! wow, easy

thheller09:03:09

^js is a standard CLJS thing for tagging a thing with a type

thheller09:03:30

ususally in clojure this would be a class typehint like ^String

hlolli09:03:36

ah yes, I've seen that

thheller09:03:47

but in CLJS we don't need classes so we only need to infer that the thing is a JS object or a CLJS object

thheller09:03:58

CLJS is fine to rename, JS will generated externs so it won't be renamed

thheller09:03:09

but you'll only get the warnings if :infer-externs :auto is on

thheller09:03:22

can't turn that on by default since it may generate too many warnings

hlolli09:03:02

ah I see, now earlier talks here on that make more sense to me

jmckitrick13:03:37

Has anyone used shadow with devcards?

jmckitrick13:03:45

If so, any special caveats?

mitchelkuijpers15:03:27

@jmckitrick we use shadow with devcards

mitchelkuijpers15:03:45

we have a file like this:

(ns atlas-crm.cards
  (:require
  .... namespaces with cards
   [devcards.core :as dc :refer-macros [start-devcard-ui!]]))

(start-devcard-ui!)

(defn refresh []) ;; Used for devcards live reload support
And a build like this:
:devcards {:target :browser
                     :asset-path "/js/devcards"
                     :output-dir "resources/public/js/devcards/"
                     :compiler-options {:devcards true :external-config {:fulcro.inspect/config {:launch-keystroke "ctrl-space"}}}
                     :modules {:devcards {:entries [atlas-crm.cards]}}
                     :devtools {:after-load atlas-crm.cards/refresh
                                :http-port 8600
                                :http-root "public" ;; We don't use this but our handler, but this makes shadow start a http server
                                :http-handler dev.test-handler/handler
                                :preloads [fulcro.inspect.preload]}}

mitchelkuijpers15:03:06

Does anyone here know the command to get the page in shadow-cljs which shows how much space each dep or ns takes

thheller17:03:31

@mitchelkuijpers (shadow.cljs.devtools.api/release-snapshot :the-build {}) then

mhuebert19:03:55

hmm, does this look like correct usage of rename-prefixing for closure? :compiler-options {:rename-prefix-namespace "App"}

mhuebert19:03:41

i’m running into some collisions with other code on a page, using :advanced compilation, and it doesn’t seem to have an effect

thheller19:03:37

@mhuebert this is not currently support because it needs special considerations for :modules

thheller19:03:53

if you just want to isolate your code add

thheller19:03:29

:modules {:main {:entries ... :prepend "(function(){" :append "})();"}}

thheller19:03:49

also problematic if you use more than one module though

mhuebert19:03:23

does that have any effect on exports?

mhuebert19:03:05

hmm. i do have two modules

thheller19:03:26

yeah thats a problem

thheller19:03:02

I have a plan for this but didn't get to it yet

thheller19:03:13

what exactly is the issue for you? would externs maybe solve it?

mhuebert19:03:33

it overwrites

mhuebert19:03:41

which an existing app uses for something

thheller19:03:26

then add externs for that, so closure won't use that name

thheller19:03:12

<project-root>/externs/your-build.txt global:io should do it

mhuebert19:03:49

ah that was that special externs file lookup/format?

mhuebert19:03:30

is :stable-names supported?

thheller19:03:47

has been the default in shadow-cljs for a couple of years. it is always on yes.

thosmos20:03:20

@thheller @lee.justin.m I was getting the same results even after I used NS requires. But after looking at the compiled output, I found a workaround. Closure was optimizing away the (.bind stmt) call, probably because it was in a let with no binding of its results (even though it returns nil). When I bound the result Closure let it through:

(let [db ^js (:db @state)
      stmt (.prepare db "SELECT * ...")
      bound? (.bind stmt ids)])
The sql.js namespace includes two JS "classes" (functions with prototype methods) of Database and Statement. I'm currently bringing them in as (ns my.app (:require ["sql.js" :as sql :refer [Database Statement])) What's the best way to import them such that I can use them as namespaces like:
(let [
db ^Database (Database. dbBuffer)  
stmt ^Statement (db/prepare sqlStr)
bound? (stmt/bind ids)])

justinlee20:03:18

@thosmos is sql.js your file or is it on npm?

thosmos20:03:26

it's from NPM

justinlee20:03:33

why not import it as an npm module?

justinlee20:03:42

i think weird shit happens when you import as javascript

thosmos20:03:57

Is that not what I'm doing here: (:require ["sql.js" :as sql :refer [Database Statement])

justinlee20:03:11

no you’re including the actual file

justinlee20:03:32

what you want to do is refer to the npm package name and then install the package in your repository using yarn or npm

thheller20:03:02

https://www.npmjs.com/package/sql.js its the package name. so everything is correct

thosmos20:03:11

Yes it's in package.json as a dependency and I use yarn to download it

thheller20:03:21

what exactly was the problem again?

thheller20:03:39

(ns my.app (:require ["sql.js" :as sql :refer [Database Statement])) that should work just fine?

thosmos20:03:56

@thheller turns out one of the function calls was getting optimized away by Closure

justinlee20:03:56

@thheller doesn’t that run it through the optimizer?

justinlee20:03:18

I thought javascript includes were optimized whereas npm includes just go through “simple”

thosmos20:03:45

one of my function calls, not the package's function calls

thosmos20:03:09

(let [db ^js (:db @state)
      stmt (.prepare db "SELECT * ...")
      _ (.bind stmt ids)]) ;; this call got elided

thheller20:03:32

@lee.justin.m I don't understand. what are you talking about? sql.js is a normal npm package so it gets treated like any other. so it goes through :simple. but simple can also remove code.

thheller20:03:08

@thosmos how did you confirm that this call specifically gets elided?

justinlee20:03:09

sorry i guess i got confused. i though that if you include a raw js file then it was treated differently. please ignore me.

thosmos20:03:16

Oh, but this is in an electron app in the UI process which is being built with :target :browser

thheller20:03:52

@lee.justin.m raw .js file requires *always* start with either / or ./. anything that does not start with those is a npm package.

thosmos20:03:55

It works when I use :js-options {:js-provider :require} but not :shadow

thheller20:03:26

@thosmos then use that. should be fine.

thosmos20:03:35

@thheller I confirmed by looking at the compiled JS that's output

thheller20:03:56

:shadow only rewrites the whole npm stuff because the browser doesn't have access to require. electron does so its totally fine to do this.

thheller20:03:27

but that would not explain why the .bind does not get removed with :require

thheller20:03:34

because that doesn't affect the generated code at all

thheller20:03:47

it is pretty much identical as far as closure in concerned

thosmos20:03:09

@thheller thanks for shadow-cljs. It's great! I love the server mode!

👍 4