[ClojureScript] Re: Javascript library (Leaflet) not linking in production build, because of member renaming?

2020-02-25 Thread 'Simon Brooke' via ClojureScript


On Tuesday, 25 February 2020 10:48:27 UTC, Thomas Heller wrote:
>
> Hey,
>
> first of all :stable-names has nothing to do with this. It only attempts 
> to keep the names stable between compiles, meaning that it will try to 
> re-use the same shortened name on a recompile. It'll still shorten though.
>
> The issue you need to google is externs and externs inference.
>
> See https://clojurescript.org/guides/externs
>
> Your leaflet.js externs are likely just incomplete, which happens quite 
> often if they are auto-generated.
>
> If you enable :infer-externs you should get warnings for things that'll be 
> renamed because the compiler cannot tell who they belong to.
>

Thank you, that was the trick!

It's working now, but I need to do a wee bit more tidy-up before I push the 
fix to github.

-- 
Note that posts from new members are moderated - please be patient with your 
first post.
--- 
You received this message because you are subscribed to the Google Groups 
"ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojurescript+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojurescript/c88ac2fe-d738-49e9-b51d-ac5d3a0c3a16%40googlegroups.com.


[ClojureScript] Re: Javascript library (Leaflet) not linking in production build, because of member renaming?

2020-02-25 Thread Thomas Heller
Hey,

first of all :stable-names has nothing to do with this. It only attempts to 
keep the names stable between compiles, meaning that it will try to re-use 
the same shortened name on a recompile. It'll still shorten though.

The issue you need to google is externs and externs inference.

See https://clojurescript.org/guides/externs

Your leaflet.js externs are likely just incomplete, which happens quite 
often if they are auto-generated.

If you enable :infer-externs you should get warnings for things that'll be 
renamed because the compiler cannot tell who they belong to.

You can also compile with :pseudo-names true which will make the names 
somewhat recognizable, meaning setView becomes $setView$. So you can add 
setView to your externs to make that error go away. That is a bit tedious 
but an alternative to infer-externs.

HTH,
/thomas

PS: shadow-cljs fixes a lot of those issues.

On Tuesday, February 25, 2020 at 10:24:31 AM UTC+1, Simon Brooke wrote:
>
> Hi all, 
>
> I've a bug which is baffling me. If you go to 
> https://simon-brooke.github.io/geocsv-lite/ you will see three maps that 
> all work. Excellent. But my guilty secret is that that is a dev build; the 
> production build does not work.
>
> If you clone the project and run
>
> lein cljsbuild once min
>
> and load a page, you'll get
>
> TypeError: L.map(...).Wf is not a function
>
> You'll get that even if you set the compile options to:
>
>{:id "min"
> :source-paths ["src"]
> :compiler {:output-to 
> "resources/public/js/compiled/geocsv_lite.js"
>:main geocsv-lite.core
>:optimizations :none
>:foreign-libs [{:file 
> "./resources/node_modules/leaflet/dist/leaflet.js"}]
>:externs ["leaflet.js"]
>:stable-names true
>:pretty-print true
>:warnings true}}
>
> If you look at the error, it happens here:
>
>   switch(c = mk instanceof G ? mk.ib : null, c) {
> case "mapbox":
>   c = L.map(a, Aj(new x(null, 1, [Xl, "false"], null))).Wf([55, 
> -4], 10);
>   L.Rg("http://{s}.tiles.mapbox.com/v3/FIXME/{z}/{x}/{y}.png 
> ", Aj(new 
> x(null, 2, [Nl, "Map data \x26copy; [...]", gl, 18], null))).ef();
>   break a;
> case "osm":
>   c = L.map(a, Aj(new x(null, 1, [Xl, !1], null))).Wf([55, -4], 
> 10);  THIS LINE HERE
>   L.Rg("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png 
> ", Aj(new 
> x(null, 2, [Nl, "Map data \x26copy; \x3ca href\x3d'
> http://openstreetmap.org'\x3eOpenStreetMap\x3c/a\x3e contributors", gl, 
> 18], null))).ef(c);
>   break a;
> default:
>   throw Error(["No matching clause: ", B.a(c)].join(""));
>   }
>
> which is clearly compiled from:
>
> (defn map-did-mount-osm
>   "Did-mount function loading map tile data from Open Street Map.
>   Arguments are:
>   * `id` the element id of the HTML element to occupy (string);
>   * `lat` the latitude of the centre of the view (real number);
>   * `lng` the longitude of the centre of the view (real number);
>   * `zoom` the initial zoom level of the view (real number)."
>   [id lat lng zoom]
>   (let [view (.setView
>(.map js/L
>  id
>  (clj->js {:zoomControl false}))
>#js [lat lng]
>zoom)]
> (.addTo (.tileLayer js/L osm-url
> (clj->js {:attribution osm-attrib
>   :maxZoom 18}))
> view)
> view))
>
> (defn map-did-mount
>   "Select the actual map provider to use. Arguments are:
>   * `id` the element id of the HTML element to occupy (string);
>   * `lat` the latitude of the centre of the view (real number);
>   * `lng` the longitude of the centre of the view (real number);
>   * `zoom` the initial zoom level of the view (real number)."
>   [id lat lng zoom]
>   (case *map-provider*
> :mapbox (map-did-mount-mapbox id lat lng zoom)
> :osm (map-did-mount-osm id lat lng zoom)
> ;; potentially others
> ))
>
> So what is going wrong is that *some* (not all) Leaflet method names are 
> being substituted, *despite* :stable-names being true.
>
> For example, above, 'L.tileLayer' is being compiled to 'L.Rg', and, where 
> it's actually breaking, 'setView' is being compiled to 'Wf'.
>
> Now, this cannot be a problem unique to me, and I find it hard to believe 
> that it's a problem unique to Leaflet. But I have googled and googled, and 
> I cannot find how to tell the ClojureScript compiler that it does not own 
> the 'L' global, and cannot rename its members. Anyone? Please help?
>

-- 
Note that posts from new members are moderated - please be patient with your 

[ClojureScript] Javascript library (Leaflet) not linking in production build, because of member renaming?

2020-02-25 Thread 'Simon Brooke' via ClojureScript
Hi all, 

I've a bug which is baffling me. If you go to 
https://simon-brooke.github.io/geocsv-lite/ you will see three maps that 
all work. Excellent. But my guilty secret is that that is a dev build; the 
production build does not work.

If you clone the project and run

lein cljsbuild once min

and load a page, you'll get

TypeError: L.map(...).Wf is not a function

You'll get that even if you set the compile options to:

   {:id "min"
:source-paths ["src"]
:compiler {:output-to 
"resources/public/js/compiled/geocsv_lite.js"
   :main geocsv-lite.core
   :optimizations :none
   :foreign-libs [{:file 
"./resources/node_modules/leaflet/dist/leaflet.js"}]
   :externs ["leaflet.js"]
   :stable-names true
   :pretty-print true
   :warnings true}}

If you look at the error, it happens here:

  switch(c = mk instanceof G ? mk.ib : null, c) {
case "mapbox":
  c = L.map(a, Aj(new x(null, 1, [Xl, "false"], null))).Wf([55, 
-4], 10);
  L.Rg("http://{s}.tiles.mapbox.com/v3/FIXME/{z}/{x}/{y}.png;, 
Aj(new x(null, 2, [Nl, "Map data \x26copy; [...]", gl, 18], null))).ef();
  break a;
case "osm":
  c = L.map(a, Aj(new x(null, 1, [Xl, !1], null))).Wf([55, -4], 
10);  THIS LINE HERE
  L.Rg("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png;, Aj(new 
x(null, 2, [Nl, "Map data \x26copy; \x3ca 
href\x3d'http://openstreetmap.org'\x3eOpenStreetMap\x3c/a\x3e 
contributors", gl, 18], null))).ef(c);
  break a;
default:
  throw Error(["No matching clause: ", B.a(c)].join(""));
  }

which is clearly compiled from:

(defn map-did-mount-osm
  "Did-mount function loading map tile data from Open Street Map.
  Arguments are:
  * `id` the element id of the HTML element to occupy (string);
  * `lat` the latitude of the centre of the view (real number);
  * `lng` the longitude of the centre of the view (real number);
  * `zoom` the initial zoom level of the view (real number)."
  [id lat lng zoom]
  (let [view (.setView
   (.map js/L
 id
 (clj->js {:zoomControl false}))
   #js [lat lng]
   zoom)]
(.addTo (.tileLayer js/L osm-url
(clj->js {:attribution osm-attrib
  :maxZoom 18}))
view)
view))

(defn map-did-mount
  "Select the actual map provider to use. Arguments are:
  * `id` the element id of the HTML element to occupy (string);
  * `lat` the latitude of the centre of the view (real number);
  * `lng` the longitude of the centre of the view (real number);
  * `zoom` the initial zoom level of the view (real number)."
  [id lat lng zoom]
  (case *map-provider*
:mapbox (map-did-mount-mapbox id lat lng zoom)
:osm (map-did-mount-osm id lat lng zoom)
;; potentially others
))

So what is going wrong is that *some* (not all) Leaflet method names are 
being substituted, *despite* :stable-names being true.

For example, above, 'L.tileLayer' is being compiled to 'L.Rg', and, where 
it's actually breaking, 'setView' is being compiled to 'Wf'.

Now, this cannot be a problem unique to me, and I find it hard to believe 
that it's a problem unique to Leaflet. But I have googled and googled, and 
I cannot find how to tell the ClojureScript compiler that it does not own 
the 'L' global, and cannot rename its members. Anyone? Please help?

-- 
Note that posts from new members are moderated - please be patient with your 
first post.
--- 
You received this message because you are subscribed to the Google Groups 
"ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojurescript+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojurescript/b354e642-93ae-4890-a317-d58f89ed2c19%40googlegroups.com.