[ClojureScript] Re: shadow-cljs and lein ring uberjar

2020-06-24 Thread Thomas Heller
Hard to say what you are doing without seeing the config. Your config is 
doing this, neither lein or shadow-cljs will do this on their own.

I typically recommend keeping things separate since that make things much 
easier to understand and debug.

shadow-cljs release app && lein ring uberjar

lein or ring don't need to do anything with CLJS other than taking the 
files shadow-cljs produced and putting them into the .jar they create. That 
typically happens automatically if you output to some folder on your 
classpath (eg. resources/public/js).


On Monday, June 22, 2020 at 9:01:35 PM UTC+2, Scott Klarenbach wrote:
>
> When I run "lein ring uberjar", after it builds the jar file it triggers 
> the shadow-cljs :app build and rebuilds all client code.
>
> I was wanting it to just build the jar file, since the client build is 
> triggered using lein prod.
>
> Is this default behavior or have I screwed something up?
>

-- 
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/a34d7b56-397a-47e8-8833-4edce7ef191co%40googlegroups.com.


[ClojureScript] Re: Maximum Stack Size exceeding in clojurescript when using with Google Maps API

2020-06-24 Thread Thomas Heller
You are passing a CLJS map into the js/google.maps.Map. call. Convert it 
via (clj->js {:center ...}) first or use the #js literal.


On Wednesday, June 24, 2020 at 8:35:14 AM UTC+2, Casey Sparrow wrote:
>
> I have the following function that loads the google maps api:
>
> ```
> (defn load-google-maps-api []
> (js/console.log "script element is " script)
>
> (set! (.-src script) "
> https://maps.googleapis.com/maps/api/js?key=AIzaSyD1r7IEMfQzY=init_delivery_map
> ")
>
> (set! (.-defer script) true)
> (set! (.-async script) true)
> (set! (.-init-delivery-map js/window)
>   (fn []
> (prn "setting delivery-map")
> (reset! delivery-map
>   (js/google.maps.Map. (js/document.getElementById 
> "delivery-map")
>{:center {:lat 37.0 :lng 
> -122.0}}
>
> (.append (js/jQuery "head") script)
>
> )
>
> ```
>
> which I call when an event is triggered. However, the line ```(.append 
> (js/jQuery "head") script)``` in conjunction with the line. (set! (.-src 
> script) "
> https://maps.googleapis.com/maps/api/js?key=AIzaSyD1r7IEMfQzY=init_delivery_map
> ")
>
>  ``
>
> cause the error:
>
> ```
> Uncaught (in promise) RangeError: Maximum call stack size exceeded
> at Object.cljs$core$array_index_of [as array_index_of] (core.cljs:6592)
> at Object.cljs$core$array_map_index_of [as array_map_index_of] 
> (core.cljs:6607)
> at ni.eval [as cljs$core$ILookup$_lookup$arity$3] (core.cljs:6892)
> at ni.eval [as get] (core.cljs:6822)
> at ni.streetView_changed 
> (js?key=AIzaSyD1r7IwW4_MfQzY=init_delivery_map&_=1592974955286:217)
> at $d 
> (js?key=AIzaSyD1r_MfQzY=init_delivery_map&_=1592974955286:63)
> at ni._.O.set 
> (js?key=AIzaSyD1r7IEvvf6w8FlMfQzY=init_delivery_map&_=1592974955286:181)
> at ni.streetView_changed 
> (js?key=AIzaSyD1r7IEvMfQzY=init_delivery_map&_=1592974955286:217)
> at $d 
> (js?key=AIzaSyD1r7IEvvf6w8FlHu3k_hP_oJwW4_MfQzY=init_delivery_map&_=1592974955286:63)
> at ni._.O.set 
> (js?key=AI_MfQzY=init_delivery_map&_=1592974955286:181)
>
> ```
>
> Suggesting that the maximum call stack is less than what it should be. 
> Because the javascript version of this code doesn't give this error and 
> works:
>
> ```
> function loadGoogleMapsApi() {
> var script = document.createElement('script');
> script.src = '
> https://maps.googleapis.com/maps/api/js?key=AIzaSyD1r7IEvvf6w8FlHu3k_hP_oJwW4_MfQzY=initDeliveryMap
> ';
> script.defer = true;
> script.async = true;
>
> window.initDeliveryMap = function() {
> console.log("init map");
> console.log("Element is ", 
> document.getElementById("delivery-map"));
> deliveryMap = new 
> google.maps.Map(document.getElementById("delivery-map"), {
> center: { lat: 37.7749, lng: -122.4194 },
> zoom: 8
> });
> };
>
> document.head.appendChild(script);
>
> }
>
>
> ```
>

-- 
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/835d8078-afac-4340-8c16-f1022d2cb7fdo%40googlegroups.com.


[ClojureScript] Re: shadow-cljs and react-window problem

2020-05-05 Thread Thomas Heller
Hey,

if you are falling back to manually calling react/createElement then you 
must ensure that you are passing it data it understands. In your example 
you are passing a CLJS map which React just identifies as a object but not 
as a props object so it thinks you meant a component and warns you.


(defn fixed-size-list []
  (react/createElement
FixedSizeList
#js {:height 400 :width 300 :itemSize 46 :itemCount 200}
render))

That should do it, or just use the reagent built-ins for native interop via [:> 
FixedSizeList {:height ...} render]

Cheers,
/thomas

On Monday, May 4, 2020 at 8:33:16 PM UTC+2, Scott Klarenbach wrote:
>
> I'm super happy and impressed with shadow-cljs, it has radically improved 
> my workflow and deployments, and exposed the npm universe without 
> ballooning my js files...so, thanks very much to Thomas Heller,
>
> I'm having an issue with react-window interop.
>
> I'm successfully importing and using several 3rd party npm modules.  It's 
> just this one that is not working.
>
> I keep getting the error:  Invariant Violation: "Element type is invalid: 
> expected a string (for built-in components) or a class/function (for 
> composite components) but got: object. Check the render method of `List`."
>
> I'm using re-frame and shadow-cljs, and the following code to initialize:
>
> ...
> (:require
> [reagent.core :as reagent]
> ["react-window" :refer [FixedSizeList]]
> ...
>
> (defn render [props]
>   (reagent/as-element [:div "hey"]))
>
> (defn fixed-size-list []
>   (react/create-element
> FixedSizeList
> {:height 400 :width 300 :itemSize 46 :itemCount 200}
> render))
>
> but always get the error above.  FixedSizeList is refered and available 
> similar to other components.  As the error says, the problem is in the 
> render of list.
>
> I've tried render returning plain hiccup, reagent elements, react 
> elements, and react classnames as strings, and for some reason the render 
> fn in clojurescript is not valid as in the javascript examples.
>
> This same general approach is working elsewhere for 3rd part components, 
> but this is the first time I'm passing a function in as the body of the 
> component, rather than as a value on the property map.
>
> Any insights are greatly appreciated.
>
> Scott.
>

-- 
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/f5ad24f7-d809-4bf1-a304-1f077b7063a7%40googlegroups.com.


[ClojureScript] Re: shadow cljs jsx file - react index default is undefined

2020-04-26 Thread Thomas Heller
I'm assuming you are trying a .js file that has

   import React from "react";

This would try to access the default export of react. Since react only 
ships CommonJS it has no default export. CommonJS and ESM interop is in a 
weird spot currently and a bit ugly.

  import * as React from "react";

This should be fine.

On Saturday, April 25, 2020 at 7:57:59 PM UTC+2, Scott Klarenbach wrote:
>
> I'm following the instructions from here: 
> https://shadow-cljs.github.io/docs/UsersGuide.html#_javascript_dialects 
> to get jsx flies compiled through babble and required in clojurescript, but 
> I keep getting the error: react index default is undefined
>
> Is this an npm/react issue?  I only have one react installed for the 
> project.
>
> thanks
> scott klarenbach
>

-- 
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/aef80105-8a40-46a4-9de2-53aff4a99b23%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 

Re: [ClojureScript] Re: How does Clojurescript compilation scales with CPU?

2020-01-17 Thread Thomas Heller
Depends on the size I'd say but in theory yes. Lots of things factor into 
the compilation times, even tiny namespaces can take a long time to compile 
if some macro just takes a long time to do its thing.

On Friday, January 17, 2020 at 11:18:21 AM UTC+1, Khalid Jebbari wrote:
>
> Thanks for the detailed answer. Does it somewhat mean that splitting code 
> into smaller namespaces can achieve faster compilation thanks to 
> parallelization ?
>
>
> On Fri, Jan 17, 2020 at 10:43 AM Thomas Heller  > wrote:
>
>> It depends on the namespaces used. In general a CLJS namespaces can only 
>> be compiled once all its dependencies have been compiled. So if those 
>> dependendencies can be compiled in parallel they will use multiple threads 
>> from a pool, which should keep all cores busy. In my experience a good 
>> balance between core count and core speed matters. If you have big 
>> namespaces that a lot of other namespaces depend on (eg. like cljs.core) 
>> then its compilation will "block" all other threads so its important it 
>> finishes fast (ie. fast cores). If you have lots a small namespaces that 
>> are mostly independent then you can get maximum parallelization (ie. many 
>> cores). 
>>
>> I have a i7-8700K 6c and there are builds that aren't able to use all 
>> cores due to the namespace setup (few very large ones). Others happily use 
>> everything. Single core difference is gigantic to my previous CPU from a 
>> macbook pro 2016.
>>
>> If you really really want to torture your CPU you can try 
>> https://github.com/mfikes/fifth-postulate or 
>> https://github.com/mfikes/coal-mine to compare.
>>
>> HTH,
>> Thomas
>>
>> On Friday, January 17, 2020 at 5:29:06 AM UTC+1, Khalid Jebbari wrote:
>>>
>>> Hello,
>>>
>>> We're using the parallel build option, and I noticed the difference in 
>>> speed between my laptop and other laptops is basically proportional to the 
>>> difference in speed of the CPUs (based on notebookcheck's benchmarks). I 
>>> have 4C/8T 7700HQ CPU and my colleagues have a 8565U iirc (some have the 
>>> 6600U). Mine is almost twice as fast in benchmarks, which is reflected in 
>>> cljs compilation times.
>>>
>>> So my question is how does the cljs compiler scale with regards to CPU? 
>>> Core count? Single thread perf? All cores frequencies? Is it capped to some 
>>> number of cores?
>>>
>>> -- 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> --- 
>> You received this message because you are subscribed to a topic in the 
>> Google Groups "ClojureScript" group.
>> To unsubscribe from this topic, visit 
>> https://groups.google.com/d/topic/clojurescript/PwpVJNrF0Zc/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to 
>> clojur...@googlegroups.com .
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/clojurescript/7a967f70-995e-49d3-9b25-a5b327689736%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/clojurescript/7a967f70-995e-49d3-9b25-a5b327689736%40googlegroups.com?utm_medium=email_source=footer>
>> .
>>
>

-- 
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/fe80b84a-4c23-4789-9b27-8f84c631d93d%40googlegroups.com.


[ClojureScript] Re: How does Clojurescript compilation scales with CPU?

2020-01-17 Thread Thomas Heller
It depends on the namespaces used. In general a CLJS namespaces can only be 
compiled once all its dependencies have been compiled. So if those 
dependendencies can be compiled in parallel they will use multiple threads 
from a pool, which should keep all cores busy. In my experience a good 
balance between core count and core speed matters. If you have big 
namespaces that a lot of other namespaces depend on (eg. like cljs.core) 
then its compilation will "block" all other threads so its important it 
finishes fast (ie. fast cores). If you have lots a small namespaces that 
are mostly independent then you can get maximum parallelization (ie. many 
cores). 

I have a i7-8700K 6c and there are builds that aren't able to use all cores 
due to the namespace setup (few very large ones). Others happily use 
everything. Single core difference is gigantic to my previous CPU from a 
macbook pro 2016.

If you really really want to torture your CPU you can try 
https://github.com/mfikes/fifth-postulate or 
https://github.com/mfikes/coal-mine to compare.

HTH,
Thomas

On Friday, January 17, 2020 at 5:29:06 AM UTC+1, Khalid Jebbari wrote:
>
> Hello,
>
> We're using the parallel build option, and I noticed the difference in 
> speed between my laptop and other laptops is basically proportional to the 
> difference in speed of the CPUs (based on notebookcheck's benchmarks). I 
> have 4C/8T 7700HQ CPU and my colleagues have a 8565U iirc (some have the 
> 6600U). Mine is almost twice as fast in benchmarks, which is reflected in 
> cljs compilation times.
>
> So my question is how does the cljs compiler scale with regards to CPU? 
> Core count? Single thread perf? All cores frequencies? Is it capped to some 
> number of cores?
>
>

-- 
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/7a967f70-995e-49d3-9b25-a5b327689736%40googlegroups.com.


[ClojureScript] Re: (failed) Attempts to inject cljs repl into 3rd party webpage

2019-08-13 Thread Thomas Heller
You cannot really inject a shadow-cljs dev build into any arbitrary page. 
It is not designed for that and will potentially conflict with the page 
itself in bad ways.

You can set :devtools {:devtools-url "https://your.host:23456"} to 
overwrite where the socket is trying to connect to. The Browser console 
will tell if you that connect fails.

DOMContentLoaded is not used by the CLJS build, not sure why you are asking 
about it. If you are trying to register an event handler for it you are 
likely just registering it too late when it has already fired.

On Tuesday, August 13, 2019 at 6:40:36 AM UTC+2, Sigmund Tzeng wrote:
>
> Hi there,
>
> Here are my steps to inject cljs repl into 3rd party webpage:
>
> 1. inject the following line via "Custom JavaScript for websites"
>
>  (function(){var d=document;var s=d.createElement('script');s.src='
> https://localhost:8090/js/main.js';d.body.appendChild(s);})()
>
> 2. *.edn file:
>
> ;; shadow-cljs configuration
> {:source-paths
>  ["src/dev"
>   "src/main"
>   "src/test"]
>
>  :dependencies
>  [[reagent "0.8.1"] ;[etaoin "0.3.5"]
>  ]
>  :ssl {} ;for shadow-cljs server, defaults to 9630 port
>  :http {:port 9630
> :ssl-port 23456
> :host "localhost"} 
>  :dev-http {8090 {:root "public"
> :push-state/headers {"Access-Control-Allow-Origin" "*" }}
>   }
>  :builds
> {:frontend
>   {:target :browser
>:asset-path "https://localhost:8090/js;
>:modules {:main {:init-fn acme.frontend.app/init}}
>}}}
>
> 3. modify main.js with no-cors mode
>
>   fetch(uri, {mode: 'no-cors'})
>
> 4. However, the browser endpoint (shown below) is never called 
>
> wss://localhost:23456/ws/worker/frontend/.../browser
>
> 5. what am i missing here? the emacs skewer-mode seem to work just fine.
>   Was wondering if DOMContentLoaded ever get fired, even so I don't know 
> how to fix/patch it.
>
>
>

-- 
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/d1c90213-c433-42bf-a8e1-3bf5500295f4%40googlegroups.com.


[ClojureScript] Re: How to require a library only if it is on the classpath?

2019-02-12 Thread Thomas Heller
That still does not allow you to do anything you couldn't do via the ns 
form directly. require outside ns is a misleading topic and is still 
completely static. It was just added to allow compiling scripts that don't 
have a ns form. You still can't do conditionals or run any other code 
inbetween them.

The reason that dynamic require is not possible in CLJS is that there is no 
sync/blocking IO in Browser JS. In Clojure you can simply do the work and 
return once everything is loaded properly. In JS you can't do that because 
you have to go async/non-blocking for the IO to load the files. So all of 
the remainder of the program would continue running and loading only start 
once the program yielded control back to the runtime. In addition to that 
the Closure Compiler doesn't really support dynamic requires in :advanced 
optimizations.


On Monday, February 11, 2019 at 11:40:35 PM UTC+1, Yuri Govorushchenko 
wrote:
>
> > Now I understand that 'require' in cljs is intended as a repl-only 
> thing  which expands to an ns form: 
> https://clojurescript.org/guides/ns-forms#_the_require_and_require_macros_macros
>
> It should be OK to have several requires at the top of the file. Source: 
> https://anmonteiro.com/2016/10/clojurescript-require-outside-ns/.
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: How to require a library only if it is on the classpath?

2019-02-08 Thread Thomas Heller
What you are trying to do in include-if-present is not possible in CLJS.

require is completely static and you can't do dynamic require outside the 
REPL.

On Friday, February 8, 2019 at 9:43:03 AM UTC+1, Henry Widd wrote:
>
> I'm trying to write some code (to run at compilation time) that will only 
> do a require if a library is present. Initially I thought of trying 
> something like this:
>
> (defmacro include-if-present []
>   (when (io/resource "foo/bar.cljc")
> '(require 'foo.bar)))
>
>
> Now I understand that 'require' in cljs is intended as a repl-only thing  
> which expands to an ns form: 
> https://clojurescript.org/guides/ns-forms#_the_require_and_require_macros_macros
>
> So, rather than 'cljs.core/require', then perhaps what'd work it to be 
> able to hook in at the point the ns forms as read initially. 
>
> Any ideas please let me know.
>
> Thanks,
> Henry
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Question about code-splitting and loading of dependent modules.

2019-02-04 Thread Thomas Heller
To me that still sounds like you are missing a (cljs.loader/set-loaded! 
:components1) call in my-app.components.common.components1. Each module 
must call set-loaded! at some point. In shadow-cljs this is taken care of 
automatically but CLJS otherwise requires that you do this manually. If you 
have the set-loaded! calls in the proper places and it should work. If it 
doesn't I'd recommend creating a fully reproducible example and report it.


On Monday, February 4, 2019 at 12:01:23 PM UTC+1, Khalid Jebbari wrote:
>
> I realize it's much better if I give the complete configuration.
>
> latest ClojureScript stable 1.10.516
> deps.edn alias: {:cljs {:main-opts ["-m" "cljs.main" "-co" "cljs-dev.edn" 
> "--compile"]}}
> cljs-dev.edn file:
>
> {:main   "my-app.core"
>  :parallel-build true
>  :optimizations  :simple
>  :output-dir "target/js"
>  :modules{:cljs-base   {:output-to  "target/js/main.js"
> :source-map true}
>   :page1   {:entries#{"my-app.layout.page1"}
> :output-to  "target/js/page1.js"
> :source-map true}
>   :page2   {:entries#{"my-app.layout.page2"}
> :output-to  "target/js/page2.js"
> :source-map true}
>   :page3   {:entries#{"my-app.layout.page3"}
> :output-to  "target/js/page3.js"
> :depends-on #{:components1}
> :source-map true}
>   :page4   {:entries#{"my-app.layout.page4"}
> :output-to  "target/js/page4.js"
> :depends-on #{:components1 :components2}
> :source-map true}
>   :page5   {:entries#{"my-app.layout.page5"}
> :output-to  "target/js/page5.js"
> :depends-on #{:components1 :components2}
> :source-map true}
>   :components1 {:entries
> #{"my-app.components.common.components1"}
> :output-to  "target/js/components1.js"
> :source-map true}
>   :components2 {:entries  
>  #{"my-app.components.common.components2"}
> :output-to "target/js/components2.js"}}
>  }
>
> So my point here is to remove code from cljs-base that is common to some 
> pages but not all of them and putting them into the split :components1 and 
> :components2. The compilation works, the split are good (I verified the 
> javascript produced for every file) but the runtime behavior is incorrect. 
> My problem is that when I load :page3 with (loader/load :page3 
> my-callback), I see a requests to components1.js with response 200 OK, but 
> no request to page3.js after, and my-callback is not executed.
>
> On Friday, February 1, 2019 at 1:01:33 PM UTC+1, Khalid Jebbari wrote:
>>
>> Hello,
>>
>> I create 3 modules in the :modules configuration, say :cljs-base, :a & 
>> :b, and know that module :a depends on code in the module :b (and in 
>> :cljs-base of course). If I manually load only :a with `(cljs.loader/load 
>> :a)`, will it automatically load :b? My local testing seems to show that it 
>> doesn't.
>>
>>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: Question about code-splitting and loading of dependent modules.

2019-02-02 Thread Thomas Heller
In standard CLJS you must add a manual call to let the runtime know that 
your module finished loading.

(cljs.loader/set-loaded! :a) 

Somewhere near the "end" of your modules. Only with this call will the 
runtime continue loading the code.

https://clojurescript.org/guides/code-splitting


-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Question about code-splitting and loading of dependent modules.

2019-02-01 Thread Thomas Heller
You didn't show your config but did you correctly configure that :a depends 
on :b? eg. :depends-on #{:b}? That can't be inferred so you must manually 
configure it.

On Friday, February 1, 2019 at 1:11:20 PM UTC+1, Khalid Jebbari wrote:
>
> In case it wasn't clear, the javascript file for :cljs-base is included as 
> a script tag in the html, and it loads :a.
>
> On Friday, February 1, 2019 at 1:01:33 PM UTC+1, Khalid Jebbari wrote:
>>
>> Hello,
>>
>> I create 3 modules in the :modules configuration, say :cljs-base, :a & 
>> :b, and know that module :a depends on code in the module :b (and in 
>> :cljs-base of course). If I manually load only :a with `(cljs.loader/load 
>> :a)`, will it automatically load :b? My local testing seems to show that it 
>> doesn't.
>>
>>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: ANN: ClojureScript 1.10.516

2019-02-01 Thread Thomas Heller


On Friday, February 1, 2019 at 5:54:13 AM UTC+1, Khalid Jebbari wrote:
>
> Can it make bundles smaller ?
>

Yes in theory, but only by a very small fraction. The cljs.core/str macro 
may emit less code in certain situations for example but after :advanced 
optimizations the difference will be very small. So I wouldn't expect any 
substantial reductions overall, it is mostly about the compile time 
warnings.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Seeking advice for a reducing the size of compiled scripts

2018-12-21 Thread Thomas Heller
Did you look into using Code Splitting aka :modules to reduce the size of 
the initial download?

Did you check where your 170KB actually come from? Including things like 
cljs.pprint can add quite a bit and isn't commonly used in production 
builds but can't be DCE'd (yet), similarly other namespaces can bloat the 
final output just by being required. Modifying the compiler to remove 
certain signatures or other tweaks is likely asking for trouble and there 
is currently no option to do this.

With that being said CLJS output is generally very competitive or even 
smaller than comparable JS builds if you account for what you are actually 
using. The Closure Library is also built for maximum compatibility which is 
less relevant these days but can still save hours of debugging if you care 
about supporting older systems, at the cost of a few extra bytes. Don't 
just compare with vanilla JS without immutable datastructures, sane 
equality semantics and so on.

Cheers,
Thomas


On Thursday, December 20, 2018 at 5:18:34 PM UTC+1, Tom Connors wrote:
>
> At work we use clojurescript to implement a front-end with minified and 
> gzipped assets coming in at around 170KB. If I can’t reduce that 
> substantially I’ll probably have to rewrite in javascript. I’m posting to 
> share some ideas I have for reducing the size of the script and to ask for 
> any additional techniques others have used to get smaller scripts.
>
> Things I can do right now:
>
>- Measure the impact of every library: I’ve found that transit adds 
>about 12KB gzipped and core.async adds even more (probably variable due to 
>the transformations performed by the go macro). Reagent is 
>surprisingly light - about 4KB. I’m using preact instead of react, so that 
>lib is an almost negligible 3KB. Importantly, I’ve found that some APIs 
>provided by google closure can have surprising impacts on script size. 
>Don’t use goog.xhr - do direct interop for http requests. 
>- Avoid multimethods and other global registries like re-frame. These 
>thwart DCE because there’s no way to know at compile time that a specific 
>method/handler is never used. 
>- Remove unnecessary parts of data structures. If you have a literal 
>vector of maps where each map has a key or two that isn’t used by code 
>(perhaps it’s just information for developers), those unused keys won’t be 
>DCE’d 
>- Make use of goog defines to get rid of code paths that you can 
>determine to be unnecessary at compile time. 
>- Avoid using apply for functions that implement a lot of different 
>arities. The clourescript compiler tends to be really smart about this - 
> if 
>you implement 1, 2, and 3 arity versions of a function and only call the 
>two arity one, the 1 and 3 arity versions can get DCE’d. If you use 
>apply, however, all the arities end up in the script. 
>- Do a second round of minification with uglify or some other 
>minifier. I haven’t tested this in a while, but when I did last time it 
>saved a KB or two. At least it compresses the Math.imul definition at the 
>top of the script. 
>
> Aside from dropping heavy libraries, those are all incremental changes. In 
> order to get really substantial size savings, I think changes would need to 
> be made to clojurescript. I have no idea about the feasibility of these 
> things.
>
>- (ideally) automatically (but probably based on configuration) remove 
>unused methods of type definitions. For example, cljs.core.UUID implements 
>the equiv method of Object. Suppose we know at compile time that we 
>will construct UUIDs but not compare them with anything. It would be great 
>to be able to remove that method’s definition. I doubt this is possible 
>without a static type system, but I wonder whether there is some way to 
>make this configurable that wouldn’t lead to an explosion of configuration 
>options and inscrutable errors. 
>- Some functions implement multiple arities for dispatch performance. 
>I would like to be able to say “I accept the performance hit in exchange 
>for only implementing one arity of this function”. For instance, 
>partial implements multiple arities of its own args and of the 
>function it returns. This could be reduced down to (defn partial [f & 
> more] 
>(fn [& args] (apply f (concat more args if we cared more about script 
>size than runtime performance. 
>
> Any other ideas?
> ​
>
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Pressure towards ever larger namespace/file

2018-10-11 Thread Thomas Heller

>
>
> The three second compile time is with :compile-dependents false, 
> :optimizations :none and :parallel-build true. I would love to know if that 
> is atypical and what I might have set up wrong.
>
>
It sounds slow but it really depends on what you are doing in the code. 
Typically using a lot of macros make the code slower to compile but its not 
impossible to reach 3 seconds with just plain code as many factors affect 
the compile performance. You could try the latest master which has a bunch 
of performance tweaks, may those 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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Is this a ClojureScript compiler bug or intended result?

2018-08-13 Thread Thomas Heller
You can use `cljs.util/debug-prn` if you need to print during macro 
expansion.

Whether or not this should be called a bug I don't know.

On Monday, August 13, 2018 at 8:41:05 AM UTC+2, Philos Kim wrote:
>
> I wrote a macro in ClojureScript and wanted to test the macro by using 
> println function like this,
>
> ;; qna/macro.clj
> (ns qna.macro)
>
> (defmacro my-add [a b]
>   (println "a =" a "b =" b)   ; <-- Here
>   `(+ ~a ~b))
>
>
> ;; qna/main.cljs
> (ns qna.main
>   (:require-macros [qna.macro :refer [my-add]]))
>
> (defn ^:export main []
>   (my-add 2 3))
>
>
> resources/public/index.html and project.clj are like the following.
>
> ;; resources/public/index.html
> 
> 
>   
> 
> QnA Demo
>   
>   
>   
> QnA Demo
>  
>
> 
> qna.main.main();
>   
> 
>
>
> ;; project.clj
> (defproject qna "0.1.0-SNAPSHOT"
>   :dependencies [[org.clojure/clojure "1.9.0"]
>  [org.clojure/clojurescript "1.10.339"]]
>   :min-lein-version "2.6.0"
>   :plugins [[lein-cljsbuild "1.1.7"]
> [lein-figwheel "0.5.16"]]
>   :clean-targets ^{:protect false}
>   ["target"
>"resources/public/js/out"
>"resources/public/js/main.js"]
>   :cljsbuild
>   {:builds
>[{:id "dev"
>  :source-paths ["src"]
>  :compiler {:main  qna.main
> :output-to "resources/public/js/main.js"
> :output-dir "resources/public/js/out/"
> :asset-path "js/out/"
> :optimizations :none
> :source-map true
> :pretty-print true} }]})
>
> When I open the above .html file in the browser, I encounter the following 
> error.
>
> Uncaught SyntaxError: Unexpected identifier in main.js:4
>
> And the compiled main.js file is like this.
>
> // Compiled by ClojureScript 1.10.339 {}
> goog.provide('qna.main');
> goog.require('cljs.core');
> a = 2 b = 3  // <-- embedded printed result
> qna.main.main = (function qna$main$main(){
> return ((2) + (3));
> });
> goog.exportSymbol('qna.main.main', qna.main.main);
>
> //# sourceMappingURL=main.js.map
>
>
> To sum up, whenever I evalute (println ...) within a macro, the printed 
> result doesn't go to the REPL but is embedded into the compiled .js file.
>
> If this is a bug of ClojureScript, I will register this error in the 
> ClojureScript JIRA.
>
>
>
>
>
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: When will the async/await feature in ES8 be introduced in ClojureScript?

2018-05-27 Thread Thomas Heller
A few notes about the current state of the proposal:

defn is not sufficient, fn itself would need to be support too. Example 
uses defn only.

Your generator examples only show yield in one direction. This is already 
pretty much possible with seqs and you can write seq->gen + gen->seq 
functions pretty easily for those. No work needs to be done for that. The 
part that is currently possible via seqs is "var x = yield;" since 
generators/yield are two-way.

Closure is changing how lanuage-in/out work. Output will be set as a 
feature-set specifying exactly which features should be compiled down or 
kept. At least that is what a recent commit [1] suggests. Input already 
pretty much detects the feature set when parsing, it is mostly used an 
optimization to skip certain work before parsing. I expect some changes 
here as well.

There would need to be a way for processing the CLJS generated code in :none. 
Since no transpilation is done for those usually (since its ES3) that would 
be an entirely new thing. Given that most developers will be running modern 
environments this might not be too critical overall though.



[1] 
https://github.com/google/closure-compiler/commit/7d00895022cb0704edd8beeabeabdcb065c365c5



On Friday, May 25, 2018 at 10:59:10 PM UTC+2, Shaun LeBron wrote:
>
> agreed that core.async is not relevant to this discussion.
>
> I suppose the main question is—how should ES6+ (ES Next) features be made 
> available to CLJS users.  Is the story going to be  "All of ES5 is 
> accessible from CLJS—but you must use an external JS file for ES Next 
> features"?
>
> (I added your transpile link to macros section. Also, I'd love to see 
> emitting ES Modules in the future, though I'm not sure of implications 
> there)
>
> On Friday, May 25, 2018 at 11:22:26 AM UTC-5, Thomas Heller wrote:
>>
>> Yes, core.async is not great for this but it was also not meant for this. 
>> The big abstraction there are channels or CSP. There are "zero" channels 
>> involved in your example so you could probably find a better abstraction to 
>> fit here.
>>
>> There are several different concurrency models and all of them have 
>> drawbacks. As I said before I'm for adding support for async/await and 
>> generators but core.async should not even be part of the argument IMHO. I'm 
>> not trying to convince anyone that core.async is the best solution ever. I 
>> remember vividly how desperately I wanted a proper Actor-like concurrency 
>> primitive when I came over from Erlang. I actually only understood the 
>> drawbacks of Actors after I learned about CSP.
>>
>> I made this example a while ago showing what Closure does when rewriting 
>> async/await to ES3.
>> https://gist.github.com/thheller/82ca9ef8a04b58aafa4624edbac383ac
>>
>> We could emit that JS code directly using a few macros. The only reason 
>> emitting the ES6+ code makes sense is due to tool support and maybe having 
>> slightly more compact code, which is probably not a factor after :advanced 
>> is done with it. We can already interop with all of it very easily, just 
>> writing equivalent code is not ideal.
>>
>> To be honest just adding support for async/await and generators alone 
>> doesn't make much sense to me. At that point we should probably look into 
>> emitting ES6+ESM directly instead and make proper use of all the features 
>> that has. Given that Closure support for ES6 is getting much better that 
>> might make sense at some point.
>>
>>
>> On Friday, May 25, 2018 at 4:45:22 PM UTC+2, Shaun LeBron wrote:
>>>
>>> Right!  The proposal mentions that go-blocks must check for a closed 
>>> channel at every step in order to exit early. So I'll revise the 
>>> title—core.async cannot stop *arbitrary* go-blocks.
>>>
>>> For example, with this staggered animation code, it's not immediately 
>>> clear to me how to exit after any step. In JS, it pulls the plug for free.
>>>
>>> (go
>>>   (dotimes [_ 3]
>>> (swap! game assoc :board cleared)
>>> (>> (swap! game assoc :board board)
>>> (>>   (swap! game assoc :board cleared)
>>>   (>>   (swap! game assoc :board collapsed))
>>>
>>>
>>> Anyone coming from the Unity game engine will recognize this feature as 
>>> the StopCoroutine function. Core.async does not have such a feature.  the 
>>> ergonomics matter!
>>>
>>> On Friday, May 25, 2018 at 3:28:49 AM UTC-5, Thomas Heller wrote:
>>>>
>>>>
>>>>> not quite! core.async doesn't allow you to cancel a go-block (to my 
>>>>>

[ClojureScript] Re: When will the async/await feature in ES8 be introduced in ClojureScript?

2018-05-25 Thread Thomas Heller
Yes, core.async is not great for this but it was also not meant for this. 
The big abstraction there are channels or CSP. There are "zero" channels 
involved in your example so you could probably find a better abstraction to 
fit here.

There are several different concurrency models and all of them have 
drawbacks. As I said before I'm for adding support for async/await and 
generators but core.async should not even be part of the argument IMHO. I'm 
not trying to convince anyone that core.async is the best solution ever. I 
remember vividly how desperately I wanted a proper Actor-like concurrency 
primitive when I came over from Erlang. I actually only understood the 
drawbacks of Actors after I learned about CSP.

I made this example a while ago showing what Closure does when rewriting 
async/await to ES3.
https://gist.github.com/thheller/82ca9ef8a04b58aafa4624edbac383ac

We could emit that JS code directly using a few macros. The only reason 
emitting the ES6+ code makes sense is due to tool support and maybe having 
slightly more compact code, which is probably not a factor after :advanced 
is done with it. We can already interop with all of it very easily, just 
writing equivalent code is not ideal.

To be honest just adding support for async/await and generators alone 
doesn't make much sense to me. At that point we should probably look into 
emitting ES6+ESM directly instead and make proper use of all the features 
that has. Given that Closure support for ES6 is getting much better that 
might make sense at some point.


On Friday, May 25, 2018 at 4:45:22 PM UTC+2, Shaun LeBron wrote:
>
> Right!  The proposal mentions that go-blocks must check for a closed 
> channel at every step in order to exit early. So I'll revise the 
> title—core.async cannot stop *arbitrary* go-blocks.
>
> For example, with this staggered animation code, it's not immediately 
> clear to me how to exit after any step. In JS, it pulls the plug for free.
>
> (go
>   (dotimes [_ 3]
> (swap! game assoc :board cleared)
> ( (swap! game assoc :board board)
> (   (swap! game assoc :board cleared)
>   (   (swap! game assoc :board collapsed))
>
>
> Anyone coming from the Unity game engine will recognize this feature as 
> the StopCoroutine function. Core.async does not have such a feature.  the 
> ergonomics matter!
>
> On Friday, May 25, 2018 at 3:28:49 AM UTC-5, Thomas Heller wrote:
>>
>>
>>> not quite! core.async doesn't allow you to cancel a go-block (to my 
>>> knowledge), which JS allows.  I added a section on this:
>>>
>>>
>>> https://beta.observablehq.com/@shaunlebron/proposal-generators-and-async-functions-in-clojurescript#coreasync
>>>
>>>
>> This is incorrect. Closing a channel can be used to "end" a loop. In 
>> addition it is possible to use alt! or alts! with an additional "control" 
>> channel (or more) and "selecting" which channel to work on.
>>
>>
>>
>> (defn foo []
>>   (let [ch (async/chan)]
>> (go (loop [i 100]
>>   (when (pos? i)
>> (> (when (>! ch i)
>>   (recur (dec i)
>> (prn :loop-terminated))
>> ch))
>>
>> (go (let [ch (foo)]
>>   (prn (>   (prn (>   (async/close! ch)
>>   (prn (>
>>
>>  
>> In addition the "loop" is dependent on the "ch" reference. If that gets 
>> garbage collected the loop will be as well, similar to generators or 
>> async/await.
>>
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: When will the async/await feature in ES8 be introduced in ClojureScript?

2018-05-25 Thread Thomas Heller

>
>
> not quite! core.async doesn't allow you to cancel a go-block (to my 
> knowledge), which JS allows.  I added a section on this:
>
>
> https://beta.observablehq.com/@shaunlebron/proposal-generators-and-async-functions-in-clojurescript#coreasync
>
>
This is incorrect. Closing a channel can be used to "end" a loop. In 
addition it is possible to use alt! or alts! with an additional "control" 
channel (or more) and "selecting" which channel to work on.



(defn foo []
  (let [ch (async/chan)]
(go (loop [i 100]
  (when (pos? i)
(! ch i)
  (recur (dec i)
(prn :loop-terminated))
ch))

(go (let [ch (foo)]
  (prn (https://groups.google.com/group/clojurescript.


[ClojureScript] Re: When will the async/await feature in ES8 be introduced in ClojureScript?

2018-05-24 Thread Thomas Heller
I'm generally in favor of "embracing the host" but both generators and 
async/await would probably require substantial rewrites of core parts of 
the compiler. It it not just about adding a small *** or *async* keyword 
somewhere. The compiler will generally emit anonymous functions at various 
places to ensure proper scoping and this can pretty easily break 
async/generator functions. Given that you'd emitting ES6+ anways however 
you could replace those with proper block-scoped lets though. Of course 
that is not a reason to not do it, just don't underestimate how much work 
this would be.

I certainly looks like the JS world is adopting async/await but given the 
rate of change in that ecosystem that might change again when the next 
thing comes along. Given that the React folks decided to implement a pretty 
substantial feature based on throwing promises I guess they are here to 
stay for a while though.

I do not think that this compares in any way to core.async however. It is a 
much more powerful abstraction which can do a lot of things async/await 
can't and anything that does can easily be achieved with core.async and a 
few helper functions/macros. Yes, core.async is not perfect either but 
someone could work on fixing the kinks.

I guess I agree that we should eventually support async/await + generators 
for the sake of full interop but not because of "issues" with core.async. 


On Thursday, May 24, 2018 at 6:58:38 PM UTC+2, Shaun LeBron wrote:
>
> thanks for posting this question.  I asked about it a few months ago on 
> slack and apparently it has come up a few times.  There is resistance (for 
> good reason), but here's a proposal I put together that might get 
> discussion going:
>
>
> https://beta.observablehq.com/@shaunlebron/proposal-generators-and-async-functions-in-clojurescript
>
> in summary, core.async doesn't solve all the problems, can be harder to 
> debug, and using the promise api directly can be unwieldy.  but there are 
> arguments against including the extra syntax.
>
> feedback appreciated!
>
>
> On Wednesday, May 23, 2018 at 11:44:06 PM UTC-5, Philos Kim wrote:
>>
>> I wonder when the async/await feature in ES8 will be introduced in 
>> ClojureScript.
>>
>> Of course, I know there is core.async in ClojureScript but I hope that 
>> the async/await feature in ES8 will be supported in ClojureScript as soon 
>> as possible.
>>
>> Does anyone know when it will be supported?
>>
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Inconsistency in creating keywords

2018-03-01 Thread Thomas Heller
Clojure follows the principle of "Garbage in, Garbage out" for a lot of 
internal functions. Meaning you are responsible for ensuring that you only 
use valid data when calling those functions as the validation itself 
carries overhead which the core fns should not have.

:a/0 fails because the reader does those checks and fails. The keyword fn 
does no checks and lets you have your invalid keywords. They are still 
invalid keywords though. Keywords are not allowed to start with numbers.

https://github.com/edn-format/edn might be a helpful reference about that 
is allowed and what isn't.

HTH

On Thursday, March 1, 2018 at 1:14:34 PM UTC+1, outr...@gmail.com wrote:
>
> I've encountered a problem when creating namespaced keywords using the 
> literal syntax, specifically using keywords which start with numbers. 
>
> If I try using the literal syntax, entering the following at the REPL, I 
> get the exception which follows it:
>
> :a/0
> ;= clojure.lang.ExceptionInfo: NO_SOURCE_FILE [line 1, col 5] Invalid 
> keyword: :a/0. {:type :reader-exception, :ex-kind :reader-error, :file 
> "NO_SOURCE_FILE", :line 1, :col 5} ...
>
> If instead I use the the keyword function, it produces the desired result:
>
> (keyword "a" "0")
> ;= :a/0
>
>
> It seems I can get away with almost anything using the keyword function. 
> For example:
>
> (keyword "a" "0/1")
> ;= :a/0/1
>
> I'm wondering then, what is the "correct" behaviour if there is such a 
> thing in this case? I know that in Clojure the behaviour appears once again 
> to be slightly different, and the main docs seem to cater more to Clojure 
> than to CLJS.
>
> Thank you,
> Ali
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Code-splitting question

2018-02-24 Thread Thomas Heller
I answered a similar question a while ago:
https://groups.google.com/d/msg/clojurescript/Gk1XA0aIxJM/Ixu45z-wkEoJ


On Friday, February 23, 2018 at 7:06:43 PM UTC+1, Khalid Jebbari wrote:
>
> Hello,
>
> Say I have 2 namespaces in CLJS/CLJC, A and B. A requires B explicitly.
>
> I want to produce a js file for each namespace, A.js and B.js. So I use 
> the code-splitting feature, and create a dedicated module entry for each 
> namespace, :A and :B.
>
> What's exactly the difference between specifying that module :A 
> ":depends-on" :B and not specifying it ? Surely the compiler can understand 
> the dependence by just analyzing the requires in code. 
>
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Problems with Clojurescript quickstart — build fails

2018-01-26 Thread Thomas Heller
You can use it with Java9 today if you add a little flag to the command line

Instead of calling

java -cp cljs.jar:src clojure.main build.clj

you call

java --add-modules java.xml.bind -cp cljs.jar:src clojure.main build.clj

That should fix it. The Java9 fix was already applied to ClojureScript 
master but it was not released yet. Until then you can just use the flag.


On Friday, January 26, 2018 at 10:20:03 AM UTC+1, Johannes wrote:
>
> Indeed, I updated to Java 9 a few day ago. Until now I didn't get any 
> problems using Clojure with Java 9. I seems I have to wait for a Java 9 
> compatible version of Clojurescript.
>
> Am Freitag, 26. Januar 2018 01:30:34 UTC+1 schrieb Phill Wolf:
>>
>> The first sentence of the Quick Start says, "The only dependencies 
>> required for this tutorial are an installation of Java 8 and the standalone 
>> ClojureScript JAR."
>>
>> The clue "Caused by: java.lang.ClassNotFoundException: 
>> javax.xml.bind.DatatypeConverter" suggests you might be using Java 9.
>>
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: ClosureScript Quick Start error on Windows

2017-12-04 Thread Thomas Heller
This is a Java9 error. It was fixed recently but has not been released yet.

You can either add "--add-modules java.xml.bind" to the java cmd arguments 
or downgrade to Java 8.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Simple es6 JS file fails to compile as foreign lib

2017-11-20 Thread Thomas Heller

IMHO :foreign-libs do too many things these days and its not clear what to 
use when or how. This feature is alpha so I expect that everything will be 
sorted out properly in the future. I fully expect the "flaws" to be 
addressed.

:foreign-libs used to refer to "foreign JS" that was not processed in any 
way and just got prepended which was a great solution at the time and had a 
gigantic impact overall. It has some scaling issues but overall it works 
well.

The biggest flaw I saw was related to mixing :foreign-libs and :npm-deps. 
One library may be using cljsjs.react (aka foreign lib) while a newer one 
maybe using "react" via :npm-deps. This would lead to a situation where you 
had 2 React instances in your page. Since everything also happens at the 
classpath level there was no proper way to "configure" it besides 
moving/deleting your node_modules folder which I think is pretty odd. 
Again: this will probably be fixed.

I didn't like some of the decisions that were made and decided to build 
something on my own to address the issues I saw in my own code/project. 
YMMV.

> The CLJS file is using JS and the JS file is using CLJS. 100% full 
interop.

This is my goal and I'm close to achieving it.

Cheers,
/thomas

PS: Someone started some boot related work started recently:
https://github.com/jgdavey/boot-shadow-cljs

PPS: I wrote some posts about my motivations and the implementation details 
in case you are interested.
https://code.thheller.com/blog/shadow-cljs/2017/09/15/js-dependencies-the-problem.html
https://code.thheller.com/blog/shadow-cljs/2017/09/15/js-dependencies-going-forward.html
https://code.thheller.com/blog/shadow-cljs/2017/11/10/js-dependencies-in-practice.html

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Simple es6 JS file fails to compile as foreign lib

2017-11-20 Thread Thomas Heller
The Closure Compiler is fully capable of this. It appears that something is 
broken, don't know what.

In shadow-cljs [1] I handle JS dependencies quite differently so not only 
does this work there it is also much simpler (IMHO).

I made a demo showcasing all of the JS interop here:
https://github.com/thheller/shadow-cljs-examples/tree/master/local-js

You can clone it and run:
npm install
npx shadow-cljs watch app
open http://localhost:9300

These two files are interesting:
https://github.com/thheller/shadow-cljs-examples/blob/master/local-js/src/demo/app.cljs
https://github.com/thheller/shadow-cljs-examples/blob/master/local-js/src/demo/foo.js

The CLJS files is using JS and the JS file is using CLJS. 100% full interop.

Note that the use of :default in the ns :require is not yet official [2].
The support for relative require (ie. "./foo") was rejected and is "never, 
ever going to happen." [3].

I consider this an experiment to explore alternatives to :foreign-libs as I 
think they are deeply flawed and should be abandoned.

It works well in shadow-cljs but please don't use it in any library until 
there is something "official" to make all of this work.

Cheers,
/thomas


[1] https://github.com/thheller/shadow-cljs
[2] https://dev.clojure.org/jira/browse/CLJS-2376
[3] 
https://dev.clojure.org/jira/browse/CLJS-2061?focusedCommentId=46191=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-46191

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] shadow-cljs - JS dependencies: Going forward

2017-09-29 Thread Thomas Heller
I implemented a new solution for dealing with JS dependencies in a browser 
context.

In short it trades a few potential byte savings for greater compatibility 
with the npm ecosystem.

I wrote about it here:
https://code.thheller.com/blog/shadow-cljs/2017/09/15/js-dependencies-going-forward.html

If you are using dependencies from NPM but currently have to jump through 
hoops to make it all work this might be a good solution for you. I am 
looking for testers and want to hear about any package that might not work. 
If you have trouble using the new :npm-deps feature of CLJS this might be a 
suitable fallback to use.

Cheers,
/thomas


PS: See discussion on reddit as well:
https://www.reddit.com/r/Clojure/comments/72wf86/shadowcljs_js_dependencies_going_forward/

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: “Seamless interaction with NPM” not so seamless

2017-09-28 Thread Thomas Heller
*“Seamless interaction with NPM” not so seamless*

This has been exactly my experience as well which is why I wrote an 
entirely new implementation for JS dependencies.

The detailed article can be found here
https://code.thheller.com/blog/shadow-cljs/2017/09/15/js-dependencies-going-forward.html

In short the implementation is much less aggressive and sacrifices some 
potential byte savings for greater compatibility with the JS ecosystem.

I added js-nacl to my demo here:
https://github.com/thheller/shadow-cljs-examples/blob/bb29828917080b143030ff557590c7c94b806ed7/browser/src/demo/app.cljs#L25-L29

The relevant bits from the config are
https://github.com/thheller/shadow-cljs-examples/blob/bb29828917080b143030ff557590c7c94b806ed7/browser/shadow-cljs.edn#L26-L28

which basically just tell the compiler to use the window.crypto property 
when require("crypto") is used.

I don't know if everything works since I know nothing about js-nacl. The 
Basic example from their README seems to work.

This is still in pre-release mode but I could some more testers with 
"troublesome" JS dependencies.



On Saturday, September 23, 2017 at 8:26:43 PM UTC+2, António Monteiro wrote:
>
> You also need to pass the `:install-deps true` compiler option from 
> 1.9.854 onwards.
>
> Some libraries are not consumable by Google Closure if they use constructs 
> like dynamic exporting and such.
>
> In any case, it looks like your problem is even another one: you're trying 
> to use a Node.js library in the browser. Obviously, `fs`, `path` and 
> `crypto` (which are Node.js builtins) are not going to be available in any 
> browser.
>
> On Friday, September 22, 2017 at 3:50:45 PM UTC-7, Krzysztof Jurewicz 
> wrote:
>>
>> Hello, 
>>
>> I want to write a simple proof-of-concept (which may eventually evolve 
>> into something more serious) GUI wallet for a cryptocurrency that I’ve been 
>> writing. As desktop libraries/languages are either not very functional or 
>> not very portable, ClojureScript plus local storage in browser as a 
>> database looks like a good choice. To make it work, I need support for 
>> Ed25519 (a public-key signature system). 
>>
>> Fortunately, there are implementations of Ed25519 compiled to JavaScript. 
>> js-nacl is a “pure-Javascript High-level API to Emscripten-compiled 
>> libsodium routines”, available also as a NPM package, and post at 
>> https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules
>>  
>> advertises “Seamless interaction with NPM dependencies”. I tried to use it, 
>> roughly in the following way: 
>>
>> ⒈ lein new reagent-frontend ercoin-wallet 
>> ⒉ Added :npm-deps {:js-nacl "1.2.2"} to :cljsbuild ⇨ :builds ⇨ app ⇨ 
>> :compiler in project.clj. 
>> ⒊ Added [js-nacl :as nacl] to :require in core.cljs 
>>
>> However :npm-deps seemed to be ignored. Fixed this by downgrading 
>> ClojureScript from 1.9.908 to 1.9.671 (BTW, these versions are not tagged 
>> in the Git repository), but then there are warnings: 
>>
>> WARNING: JSC_JS_MODULE_LOAD_WARNING. Failed to load module […] at […] 
>>
>> , where modules are “fs”, “path” and “crypto”. 
>>
>> spinningtopsofdo on IRC said that “From a quick skim for js-nacl it looks 
>> like it's using emscripten and doing some unique module loading that Google 
>> Closure isn't aware of (
>> https://github.com/tonyg/js-nacl/blob/master/lib/nacl_factory.js#L30-L39).” 
>> and “I think it's more the way js-nacl is using ASM / Emscripten and 
>> creating JavaScript Modules. :npm-deps covers the common JavaScript module 
>> patterns (e.g. CommonJs, Node, UMD) but there is still many edge cases out 
>> there”. 
>>
>> I’ve tried also tweetnacl-js, but similarly there is a warning: 
>>
>> “WARNING: JSC_JS_MODULE_LOAD_WARNING. Failed to load module "crypto" at 
>> […]”. 
>>
>> What is the status of NPM interoperability then? Is it supposed to work 
>> as plug & play or does it require hacky knowledge in some cases? 
>>
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Compilation - Modules, and npm's vendor.js behavior

2017-09-21 Thread Thomas Heller
The usual CLJS tools do not support this but shadow-cljs [1] does.

Closure has a variable and property map feature that will save the names it 
used on one compile which can then be imported on the next compile. 
shadow-cljs does this automatically and as long as you don't remove the map 
files the naming will be stable. Sometimes due to code motion the hash of 
the file overall changes but that should only happen if you make bigger 
changes. I have been using this for a while and caching is definitely 
improved by this.

There is a very old blog post [2] that talks about this feature. See "Short 
Names Aren't Necessarily Better".

[1] https://github.com/thheller/shadow-cljs
[2] 
http://closuretools.blogspot.de/2011/01/property-by-any-other-name-part-3.html

On Thursday, September 21, 2017 at 6:22:38 PM UTC+2, Scott Klarenbach wrote:
>
> I was hoping that by splitting my code into modules I could emulate npm's 
> vendor.js behavior - where massive dependencies like React and Material UI 
> go into a separate file and app.js goes into it's own file.  This doesn't 
> help initial load but greatly helps subsequent loads since vendor.js is 
> cached by the browser and I can update my app without resending the 
> unchanged majority of the code.
>
> So, I put my "vendor" code into one module and my app code into another. 
>  It does split it correctly, with 90% of the code ending up in one big 
> vendor.js file and my app in another.  But the problem is, everytime I 
> rebuild, the closure compiler chooses new short names for the vendor.js 
> file and so it can't be cached and makes the approach useless.
>
> Is there anyway to use advanced mode and have the closure compiler use the 
> same shortened names each time?  The vendor js file doesn't change much 
> from build to build except a few variable names are always different.
>
> Thanks.
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Including a cljs namespace automatically apon use of clj macro

2017-07-18 Thread Thomas Heller
You can easily achieve this by creating a CLJS namespace that self-requires 
the macros. Having dedicated .macros namespaces is generally not 
recommended.

pixi/something.cljs
(ns pixi.something
  (:require-macros [pixi.something]))

pixi/something.clj
(ns pixi.something)

(defmacro foo [..] ..)


user/code.cljs
(ns user.code
  (:require [pixi.something :refer (foo)))

(foo)

The user code does not need to worry about whether foo is a macro or not, 
it is handled transparently by the compiler. You never need to 
:refer-macros or :require-macros in the user code this way. And you can 
manage dependent CLJS namespaces that only the macro uses by requiring them 
in the .cljs companion file.

HTH,
/thomas

On Monday, July 17, 2017 at 4:54:38 PM UTC+2, cri...@procrustes.net wrote:
>
> Hi there,
>
> I have a macro for use in cljs that injects code to make a function call 
> to a function in a cljs namespace.  Now when I use that macro I have to 
> :require the corresponding cljs namespace or during compilation I am 
> flooded with superfluous: "WARNING: Use of undeclared Var 
> mycljsnamespace/func at line " messages.
>
> Is there a way to make the use of the macro in a cljs namespace add the 
> cljs require statement to ensure that these warnings are suppressed?
>
> The function call in the macro is here: 
> https://github.com/infinitelives/infinitelives.pixi/blob/master/src/clj/infinitelives/pixi/macros.clj#L36
>
> and when using it, the compilation looks like:
>
> WARNING: Use of undeclared Var 
> infinitelives.pixi.canvas/get-default-canvas at line 15 src/cljs/...
> WARNING: Use of undeclared Var 
> infinitelives.pixi.canvas/get-default-canvas at line 15 src/cljs/...
> WARNING: Use of undeclared Var 
> infinitelives.pixi.canvas/get-default-canvas at line 11 src/cljs/...
> ...
>
> at this stage in my present project its at least 50 lines of these.
>
> if I require that name space in the client code that warning disappears 
> but that requires the user of the macro to know that in advance, and be 
> disciplined enough to do it.
>
> How do I *auto require* the namespace, when the macro is used?
>
> I found this thread from 2013: 
> https://groups.google.com/forum/#!searchin/clojurescript/require$20in$20macro%7Csort:relevance/clojurescript/FNwwN87B2EE/lLF-Tel977AJ
>
> In it, Jozef Wagner states: "AFAIK there is no way to do this 
> automatically"
>
> Is this still the case?
>
> I see CLJS has supported since 1.9.293 : CLJS-1346: Support require 
> outside of ns
>
> Can I make the macro inject the require into its output code so the 
> "WARNING: Use of undeclared Var" is not emmitted?
>
> I have experimented with this but have been unable to make it work.
>
> Is this possible to do? If so, how can this be done?
>
> Regards
>
> Crispin
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: A new take on ClojureScript and npm

2017-07-10 Thread Thomas Heller


> Yes.  Currently optimization is something we are doing when compiling 
> clojurescript, but perhaps *ideally* optimization could be done after 
> bundling when all the javascript is available.   However, I realize this 
> may not actually work very well in practice since most modern js 
> applications include dozens or hundreds of npm libraries that are not 
> closure ready and would break in unexpected ways.  Perhaps this is why 
> UglyifyJS is more common for webpack users?  UglyifyJS does dead code 
> elimination as well I believe, is it as good? probably not? is it good 
> enough? not sure.
>


UglifyJS is not good enough in my opinion, not even close. The JS world has 
"accepted" that you need to make lots of many small files to make it 
acceptable. We don't since we have Closure.

 

> Do we still need analyzer data after its compiled? Can't we just use the 
> javascript as a lib? I assume that google closure isn't written in cljs but 
> cljs has no problem using or optimizing it... perhaps the packages are 
> distributed as unoptimized google closure compatible js and the webpack 
> plugin turns google closure modules into commonjs modules? not sure. just 
> ideas. 
>


You need to analyzer data if you want to compile any .cljs. It is not 
needed at runtime (which is where the closure library comes in).

 

> Best optimized perhaps, but possibly not the best js dev ux.  Many js 
> developers don't want to run java as part of their build process and might 
> prefer to use uglifyjs even if the results are not as good.  
>

But many js devs do optimize and the best results would probably be to put 
> the unoptimized closure together with the unoptimized javascript and then 
> optimize everything together. But my guess is that wont work in practice. 
>  UglifyJS I think is safer than closure, as good? probably not, good 
> enough? not sure.  Your solution probably produces best optimization, but 
> its worth asking if thats what devs care about the most?  Slower build 
> process with more complexity vs a faster website.  There will be devs on 
> both sides I think. 
>


This is one place where it is far more important to optimize for production 
users not the developer UX. I care very little about the fact that my 
production build may take a while longer if the resulting .js my users have 
to download is substantially smaller with much better runtime performance. 
The fear of Java is unreasonable and mostly FUD. If I run builds with 
create-react-app or create-react-native-app they are frequently much slower 
than a :advanced compiled CLJS build.

There are still lots of places where we can optimize the dev UX but 
production concerns will always come first.

JS integration is still a work in progress and will get a whole lot better 
soon. Stay tuned. ;)

/thomas
 

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: A new take on ClojureScript and npm

2017-07-09 Thread Thomas Heller
Hey,

I understand what you want to achieve and I definitely want to make the 
whole thing easier but some issues don't have an easy solution.

TL;DR: It's complicated.

First we need to split compilation and bundling.

CLJS->JS compilation just takes one .cljs file and compiles it to .js. To 
do that it needs analyzer data of all CLJS dependencies. If you were to 
publish compiled CLJS to npm you'd need to also ship the analyzer data 
somehow. The other problem is that certain compiler options affect the 
generated JS which means that for every .cljs file there are many possible 
.js results. Another thing is that you also need to account for the 
compiler version since that may also affect the output or the analyzer data 
which then may affect other files.

The second part is bundling things together, which means reducing the 
number of individual files down to a more reasonable number. shadow-cljs 
enables JS tools to do that for us (eg. webpack, create-react-app or any 
other), since those tools use "require" to discover dependencies.

The best option for this however is to use the Closure Compiler but to get 
the whole benefit of it you need to optimize your whole program, which 
includes EVERY .js file. There is promising progress in Closure to support 
optimizing common js and ES6 code but it is not quite there yet and can't 
compile everything. It will be coming to shadow-cljs soon though, it is 
already in CLJS but I didn't hook it up yet since I wanted to solve some 
issues first. 

:npm-module tries to bridge the gap a little but as soon as you don't 
optimize your whole program you need externs to teach Closure about the 
things it can't see. Which means you can still use :advanced compilation 
for the CLJS/Closure parts but the rest of the code remains untouched. It 
also means that you need a second bundler (eg. webpack) to then combine the 
Closure output with the remaining unoptimized parts.

Given all these constraints I don't think it is feasible to publish 
compiled (but unbundled) CLJS code as a library to NPM. It would be 
relatively easy to consume uncompiled .cljs code from NPM packages but 
unless everybody agrees to do that it would just make things a whole lot 
more complicated for everyone. Maven is also a whole lot better than NPM 
IMHO, npm or yarn just have better UX (until something breaks).

:npm-deps is a feature in CLJS that lets you declare which npm packages 
your CLJS code requires to work. Technically this would need a complement 
in package.json to allow declaring which CLJS packages the JS code needs. I 
don't have a solution for that and I was and still am opposed to whole idea 
of :npm-deps. It does however solve the issue from the CLJS perspective, 
just not from the "Play as a Team" JS perspective.

I do want integration to be painless and I do think shadow-cljs already 
makes life easier for some. I am very interested to hear about any other 
pain points people may have with CLJS<->JS interop. I tested webpack, 
create-react-app and create-react-native-app. They are all work reasonably 
well but I haven't gone beyond basic examples.

I really don't have a good solution for the problem since part of the 
solution must come from the JS world and I have basically no idea what 
people are doing over there.

The whole problem basically boils down to which bundler you want to use.

I'm personally only considering the Closure Compiler for that and 
shadow-cljs is trying to make that as easy as possible with support for 
common JS / ES6 coming soon.

If you want to use webpack or so that also works reasonably well already 
but CLJS really is built with the Closure Compiler in mind so the end 
result of this won't be optimal.

If you want both that is always going to require more manual work for 
:externs and come with certain caveats.

I hope that made some sort of sense, I have been thinking about this a lot 
but haven't gotten very far.

/thomas

On Sunday, July 9, 2017 at 3:29:15 AM UTC+2, Kurt Harriger wrote:
>
> Thomas,
>
> First thank you for starting this project!
>
> I recently joined a team at Atlassian that uses ClojureScript to support 
> collaborative editing.  I don't think I need to sell the community here on 
> the advantages of ClojureScript, but I think packaging still needs work.
>
> If you use ClojureScript for your entire UI you probably don't have any 
> issues, but in larger organizations we need to "Play as a Team." It does 
> not seem feasible or reasonable to expect that other teams switch to using 
> the ClosureScript compiler and make their js libraries play nice with 
> closure because the end result will be marginally better, especially given 
> the work involved in ensuring they still work with advanced optimizations 
> may be non-trivial.
>
> The only practical alternative I'm currently aware of is to precompile the 
> ClojureScript with optimizations and have them include this as a script tag 
> in their page.  The disadvantages of this 

[ClojureScript] Re: Trying to get "how to use Clojurescript in node.js" to work

2017-06-16 Thread Thomas Heller
.
├── build.clj
├── cljs.jar
└── src
└── hello_world
└── core.cljs

Forgot the build.clj.

On Friday, June 16, 2017 at 9:05:14 PM UTC+2, Thomas Heller wrote:
>
> ├── cljs.jar
> └── src
> └── hello_world
> └── core.cljs
>
>
> This is the structure you should have. Its a bit confusing since you have 
> src\hello_world\src.
>
>
>
>
>
>
>

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Trying to get "how to use Clojurescript in node.js" to work

2017-06-16 Thread Thomas Heller
├── cljs.jar
└── src
└── hello_world
└── core.cljs


This is the structure you should have. Its a bit confusing since you have 
src\hello_world\src.






-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Trying to get "how to use Clojurescript in node.js" to work

2017-06-16 Thread Thomas Heller
C:\Users\Michael\Documents\src\hello_world>java -cp "cljs.jar;src" clojure.main 
node.clj

Don't run java in the hello world directory. Run it in C:\Users\Michael\
Documents

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: A new take on ClojureScript and npm

2017-05-21 Thread Thomas Heller
I made a quick video showing how you'd use what we have talked about here 
with "create-react-app".

https://www.youtube.com/watch?v=BLDX5Twt2zk


-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: A new take on ClojureScript and npm

2017-05-17 Thread Thomas Heller
The shadow-cljs compiler already does the correct thing when it comes to macros 
and recompiles all affected CLJS files.

It does however know nothing about JS files that may be affected as well so it 
would not reload those. I don't know if the webpack HMR will reload dependent 
files?

Does it reload ./index.js if that does require("shadow.cljs/some.foo") and 
some.foo was recompiled?

I have never even seen a HMR config, can you share one so I can try a few 
things?

On Wednesday, May 17, 2017 at 12:48:18 PM UTC+2, Jiyin Yiyong wrote:
> Just realized that ClojureScript is different from CoffeeScript because of 
> the macro system. If a macro changed, it may cause changes of multiple files. 
> So that it's hard to just detect which file changed and compiled it alone. 
> The only window left is to read and compare file content before writing, if 
> we are trying to get rid of the unnecessary change events...
> 

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: A new take on ClojureScript and npm: The Other Side

2017-05-17 Thread Thomas Heller
Quick Update: Just renamed the repo/artifact to thheller/shadow-cljs. Got tired 
of having to differentiate between shadow-devtools and shadow-cljs.

Release coming later today.

Github should take care of redirecting all the old links.

This is the new home:
https://github.com/thheller/shadow-cljs

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: A new take on ClojureScript and npm

2017-05-17 Thread Thomas Heller
On Wednesday, May 17, 2017 at 3:51:14 AM UTC+2, Jiyin Yiyong wrote:
> I don't like the way of writing `x.assoc(null, 'foo', 'bar')` by myself. Also 
> I don't people would accept that.
> 


I wouldn't as well, but that was an example to show that you can use CLJS code 
directly without modifying it in any way.

import { assoc } from "shadow-cljs/cljs.core";
assoc(null, "foo", "bar");

also works. assoc is an ugly example because of the leading null but it is the 
shortest form to replace the CLJS {} empty map literal. {} would mean empty JS 
object which doesn't work with assoc.

> I see the problem now. ClojureScript compilers may have tricky behaviors that 
> make it different from CoffeeScript's compiling processes.
> 

The compiler is pretty straightforward actually, the tricky parts are the 
version conflicts. If there was a way to ensure that everything always used the 
exact some compiler configuration/version this would be possible, but there is 
not AFAICT.

> Putting `x.cljs` files in npm is fine, it's just slower. To me compiling 
> ClojureScript is always slower, I already accepted that.
> 

[:script] Build completed. (23 files, 1 compiled, 0 warnings, 0.12s)

I think 0.12s is pretty fast. That is running in --dev mode recompiling one 
changed file with hot-reload enabled.

Of course it is slower if you always run "shadow-cljs --once" which includes 
starting the JVM each time. "shadow-cljs --dev" will be substantially faster 
when re-compiling.



> 
> I think here are may main concerns:
> 
> 
> * in js projects, we regard code in `node_modules` are modules instead of 
> source code. For web projects using Webpack, I would prefer using a 
> 'compiled/' folder to hold the code and then config `resolve.alias` to make 
> sure I import the code with `require('cljs/foo.bar.core')`. 
> https://webpack.js.org/configuration/resolve/
> 

Not sure what you mean. Where is the difference in putting code into 
node_modules or compiled then using webpack? The behavior is identical, the 
node_modules version just doesn't need the resolve.alias? Both versions require 
that you have your code compiled before running webpack, which directory you 
load them from should be automatic?


> *  For nodejs projects, somehow I can accept the solution that we use 
> `require('../../compiled/foo.bar.core')`. But I guess it may bring problems, 
> which makes your `shadow-cljs` solution a better choice...
> 

Yes, I hate relative paths. Actually the output folder where things end up is a 
config option. So if you really wanted to have your compiled folder that can be 
done. I just don't see an upside to it.

> 
> * does shadow-devtools compiled cljs files incrementally? If it does, Webpack 
> may use it to hot replace module.
> 

Yes, incrementally. Don't know anything about HMR but shadow-devtools already 
has hot-reloading (ala figwheel) built-in. I just didn't enable it yet because 
other things were more important.

Can't tell if Webpack HMR would work since I have never used it.

Thanks for the feedback, I hope I lessened your concerns.

Keep it coming.

Remember: this is evolving as we discuss it, I have no idea what JS devs want 
so without feedback I'll be building what I want. That may or may not align.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: A new take on ClojureScript and npm

2017-05-16 Thread Thomas Heller
On Tuesday, May 16, 2017 at 8:27:44 PM UTC+2, Thomas Heller wrote:
> If I understand correctly the short answer is: no.
> 

I should add: You can use shadow-cljs in your coffeescript project if you just 
want to use cljs.core or some other CLJS package. You do not need to write CLJS 
yourself to make use of shadow-cljs.

var x = require("shadow-cljs/cljs.core");
x.assoc(null, "foo", "bar");

is basically the same as

var x = require("mori")
x.assoc(null, "foo", "bar");

But you would need to run shadow-cljs in your project.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: A new take on ClojureScript and npm

2017-05-16 Thread Thomas Heller
If I understand correctly the short answer is: no.

I chose this setup specifically to avoid anyone ever putting compiled CLJS code 
in npm packages. The problem with this would be that everyone would bring their 
own cljs.core version again.

That is an issue currently when you write a npm package in CLJS and publish to 
npm. Each package contains its own conflicting version of cljs.core (and maybe 
others) even if you compile with :advanced.

All CLJS sources must be compiled with the same CLJS compiler, you cannot use a 
precompiled "some-package/cljs.core.js" as there is no way to guarantee that 
everyone was using the same version and so on. The way npm resolves version 
conflicts is by creating nested node_modules folders.

./node_modules/A
./node_modules/shadow-cljs (v1.0)
./node_modules/B
./node_modules/B/node_modules/shadow-cljs (v1.1)
and so on.

There is no way to ensure that B uses the same shadow-cljs version as A. By not 
having any compiled CLJS code in any npm package we can sort of get away with 
it though.

See:
https://docs.npmjs.com/how-npm-works/npm3-nondet
https://docs.npmjs.com/how-npm-works/npm3-dupe

yarn fixes some of these issues but not all.

I do however think that it would be relatively straightforward to put 
uncompiled CLJS code into npm packages and have them picked up by shadow-cljs.

So if you have

./fancy-package/src-cljs/fancy/foo.cljs

You could just require("shadow-cljs/fancy.foo") and (:require [fancy.foo]) to 
use that. While you can still require("fancy-package") normally if there also 
was JS code but never require("fancy-package/fancy.foo").

It's a bit confusing but I repeat: there must never be compiled CLJS code in a 
npm package, only uncompiled .cljs files just like we do in CLJS .jar files 
published to clojars (or maven). For now I do recommend using the normal CLJS 
methods to publish CLJS libs. Publishing to npm would be something only 
currently supported by shadow-cljs and that would not be a good idea (for now). 
Things need to be ironed out first.


I cannot explain this very well, as I am still very confused about it myself.

Sorry if you wanted something completely different.


On Tuesday, May 16, 2017 at 7:54:41 PM UTC+2, Jiyin Yiyong wrote:
> Fascinating.. it's using `node_modules/shadow-cljs` to do the trick. I can 
> see ClojureScript files are compiled into CommonJS compatible form...
> 
> 
> Do you think it's possible that we put all js built from `cjs.core`(also with 
> `goog`) into a single npm package. And then for each ClojureScript file, it 
> is mapped to a JavaScript file by `shadow-cljs` tools, which use 
> `require("./cljs.core.js");` to access it's cljs dependencies(like in your 
> demo), and use `require('package_name/foo/bar')` to require sibling files. 
> For other packages, maybe we can do the some trick, like precompile them with 
> `shadow-cljs` tools and then release them to npm. Seeing from a CoffeeScript 
> user, I think somehow in this way ClojureScript can also fit into npm's 
> ecosystem.
> 
> 
> Here's an example, we may create a new project in such file structure, where:
> 
> 
> `src/` is for source code,
> `target` is for compiled code,
> `package.json` is copied from `assets/package.json` to `target/package.json`,
> 
> 
> ```
> .
> ├── assets
> │   └── package.json
> ├── project.clj
> ├── src
> │   └── demo
> │       └── main.cljs
> └── target
>     ├── demo
>     │   └── main.js
>     └── package.json
> ```
> 
> 
> if it's in this way, `target/` can be released on npm as a module and others 
> surely may use `require('package_name/demo/main.js')` to load the package 
> built from ClojureScript.
> 
> 
> 
> 
> 
> 
> On Wed, May 17, 2017 at 12:15 AM Thomas Heller <th.h...@gmail.com> wrote:
> 
> 
> > 1. Should we call this "cljs-require"?  With the understanding that it is a 
> > bit like a portal to cljs's ":require" form:
> 
> >
> 
> > require('cljs-require/foo.core')
> 
> 
> 
> The package name must be something you add to your package.json, otherwise 
> yarn will nuke the directory every time you run "yarn install". "npm" isn't 
> as strict but still. Using the name of the tool seemed like the obvious 
> choice. We can however create an empty cljs-require npm package that just 
> serves as a placeholder.
> 
> 
> 
> I'm totally for this if other tools want to adopt this idiom. I definitely do 
> not want this to be something you can only do with shadow-cljs.
> 
> 
> 
> 
> 
> > 2. Is there a way to set the ClojureScript version, or is it tied to 
> > shadow's version?
> 
> 
> 
> You can specify dependencies in package.json, basically like you would in 
> lein.

[ClojureScript] Re: A new take on ClojureScript and npm

2017-05-16 Thread Thomas Heller
I wrote a short introduction here:
https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-JS-Devs

Looking for any kind of feedback.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: A new take on ClojureScript and npm

2017-05-15 Thread Thomas Heller
Too tired to make a proper announcement but I just pushed the first preview 
version of the shadow-cljs npm package.

https://www.npmjs.com/package/shadow-cljs

npm install -g shadow-cljs
shadow-cljs --once
node
var x = require("shadow-cljs/cljs.core");
x.enable_console_print_BANG_(); // oops
x.prn(x.assoc(null, "foo", "bar"));

More tomorrow ...

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: A new take on ClojureScript and npm

2017-05-15 Thread Thomas Heller

> 
> I think it should be possible to use closure-compiler-js [1] with this 
> project to do DCE if needed.
> 

In a way you can and you can't. The same way :npm-deps has issues.

The Closure Compiler (JS or JVM version, doesn't matter) is not yet capable of 
compiling everything in the npm world. Some things just don't work.

So instead of making something that "maybe" works I opted to drop the Closure 
Compiler entirely.

The intent here is to enable JS devs to start using CLJS seamlessly without 
giving up their tools. They don't have the Closure compiler to begin with so 
they won't miss it.

Enabling the Closure Compiler is my top priority though. I'm definitely keeping 
my eye on this and will provide a proper solution if it ever becomes solid.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: A new take on ClojureScript and npm

2017-05-15 Thread Thomas Heller
Also removed all traces of lein, the examples now just use an uberjar of 
shadow-devtools.

Certainly not the final solution I have in mind but getting closer.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: A new take on ClojureScript and npm

2017-05-15 Thread Thomas Heller
I just did a quick test for React Native.

https://github.com/thheller/npm-module-example/tree/master/examples/react-native-example

Since it is the first time I started react-native I really have no idea what is 
going.  It works but is extremely slow to start. I don't know why, just wanted 
to see if it can work at all.

If someone has suggestions on how to make it start faster let me know, also 
need to look into their HMR which doesn't seem to work.



-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: A new take on ClojureScript and npm

2017-05-15 Thread Thomas Heller
On Monday, May 15, 2017 at 8:30:26 AM UTC+2, Shaun LeBron wrote:
> > The example still uses leiningen by I may drop that and create something 
> > standalone.
> 
> I'd like to show you around my "cljs/tool" some time for your standalone 
> thing. I'm a year into building it to wrap a good UX around cljs on npm 
> things as they become available, and I think this experimental feature could 
> be delivered pretty easily through it.

Hey Shaun,

I've been following your work on github.com/cljs pretty much since the 
beginning. It would safe me a ton of work if you want to cover the npm package 
side of things.

My plan so far was:

- create an uberjar for shadow-devtools (which would contain clojure, 
clojurescript, core.async and could add more)
- create a npm package with a shadow-cljs bin that uses java or node-jre
- shadow-cljs cli opts --watch --repl etc
- zero conf CLJS compilation mode that compiles to the shadow-npm module to 
quickstart things

When the user is ready to go into full-blown CLJS first mode it should be as 
simple as creating a build config and then running the full featured mode which 
includes Google Closure.

The hard part for that transition would be that the 
require("shadow-npm/cljs.core") would no longer work since it is pretty much 
impossible to make that work with :advanced.

The results of "webpack -p" on the shadow-npm thing are ok but nowhere close to 
what Closure would give you. I guess it is good enough if you are JS first with 
a bit of CLJS sprinkled on top.

I have no attachments to the shadow-cljs or shadow-npm names, I just used them 
because there already are so many cljs+npm, clojurescript+npm variations out 
there that I just didn't want to conflict with.

If you want to use this for your cljs/tool I'd be happy to make any changes 
you'd need. Although your current mix of lumo and figwheel really doesn't 
translate too well to the "create a pseudo node module" (ie. 
"./node_modules/shadow-npm/cljs.core.js" to enable 
require("shadow-npm/cljs.core"). Also the configs for shadow-devtools are 
substantially different from lumo/figwheel/cljsbuild, hopefully simpler though.

Currently it is all driven by this little CLI ns:
https://github.com/thheller/shadow-devtools/blob/master/src/main/shadow/npm/cli.clj

I just use it through leiningen since I didn't want to work through the 
dependency management, but you already have that covered. lein is not needed at 
all beyond that.

Since I'm not a JS dev and have been purely CLJS for 3+ years I really don't 
feel qualified to make decisions on what would be ideal for a JS dev. Current 
solutions all felt unnecessary complex though.

Happy to consider all feedback.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: A new take on ClojureScript and npm

2017-05-14 Thread Thomas Heller
Yes, currently it is just shadow-devtools via lein. Could also run it through 
boot, no problem.

I want to package it all up so you can "npm install shadow-npm".

Need to figure out how to best do that first though. Should probably also chose 
a better name.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: A new take on ClojureScript and npm

2017-05-14 Thread Thomas Heller
Just added another example that shows how you'd use CLJS in a create-react-app 
setup.

https://github.com/thheller/npm-module-example/tree/master/examples/create-react-app

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: Any chance we can fit ClojureScript into Webpack ecosystem?

2017-05-14 Thread Thomas Heller
I started a new topic [1] for the implementation.

You can find an example here:
https://github.com/thheller/npm-module-example

I'd be very interested in feedback from people that actually use webpack 
already.

[1] https://groups.google.com/forum/?fromgroups#!topic/clojurescript/AGXku7Ous0Y

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] A new take on ClojureScript and npm

2017-05-14 Thread Thomas Heller
Hello,

I wrote a few lines of code that should hopefully make it easier to get started 
with CLJS for people coming from the JS world.

I created a demo here:
https://github.com/thheller/npm-module-example

The gist is that you gain: var foo = require("shadow-npm/demo.foo");

Where "shadow-npm" is a pseudo node-module generated by the tool and "demo.foo" 
is just the CLJS namespace you want. The require will return the NS so 
foo.bar() just works. The CLJS sources can use any npm module and local sources 
as well.

See: 
https://github.com/thheller/npm-module-example/blob/master/src/main/demo/foo.cljs

Given that the generated code is NPM compliant it should work with any npm JS 
tools. The demo has a basic setup for webpack, no special configuration for 
CLJS is needed.

I barely know anything about any NPM tools so I might be doing something 
completely wrong, please create issues on the shadow-devtools [1] project if 
you run into issues. I only tested node itself and webpack.

The sacrifice is that you can't use the Closure Compiler but you gain 
everything the npm world has to offer with hopefully seemless interop. Do not 
underestimate the impact of this sacrifice though, I cannot recommend using 
this for production builds.

The example still uses leiningen by I may drop that and create something 
standalone.

Need to work on a lot of things still but the proof of concept works, maybe it 
is useful to someone.

Cheers,
/thomas

[1] https://github.com/thheller/shadow-devtools

PS: This is not related to :npm-deps at all.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: Any chance we can fit ClojureScript into Webpack ecosystem?

2017-05-13 Thread Thomas Heller

> I'll probably write the simple version today and see how things work out.

So the simple version sort of works.

http://thheller.com/webpack-cljs-preview/index.html
http://thheller.com/webpack-cljs-preview/bundle.js
This was generated by "webpack -d" and

index.js:
---
var foo = require("webpack-cljs/dummy.foo");
console.log(foo.bar());
---

dummy/foo.cljs:
---
(ns dummy.foo)

(js/console.log "dummy.foo")

(defn bar []
  "bar")
---

Nothing special but works well enough, still haven't figured out most of the 
webpack things though. Currently they shadow-devtools just runs independently 
and generates files into ./node_modules/webpack-cljs/dummy.foo.js to make the 
require "pretty" (I really do not like  relative paths).

Will polish things a bit and maybe provide a public repo tomorrow. Still 
convinced that this is a very bad idea though. ;)

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: Any chance we can fit ClojureScript into Webpack ecosystem?

2017-05-13 Thread Thomas Heller
On Saturday, May 13, 2017 at 3:47:01 AM UTC+2, Jiyin Yiyong wrote:
> Cool Hope one day it's in Lumo too XD

Not by me but the features could certainly be ported.

I spent quite a bit of time yesterday fighting through webpack sources trying 
to come up with an efficient way of doing things.

The easy solution would be to make everything one-way which means JS can 
require CLJS but CLJS cannot require "local" JS, only modules from npm. So 
(js/require "react") would work but (js/require "./foo") would not.

So in JS you would could say var x = require("webpack-cljs/cljs.core"). The way 
things are handled in webpack/npm means you must have a module-name which would 
be webpack-cljs or something along that line. But a package cannot depend on 
the local sources.

Having sources to actually be side-by-side doesn't mirror too well to JS since 
you usually don't have namespaces there.

Imagine
src/index.js
src/foo.js
src-cljs/foo/bar.cljs

In index.js you could say require("./webpack-cljs/foo.bar") and in the cljs 
file I could imagine
(webpack/require "./foo") where it would always be relative context root (ie. 
src). The compiler would actually just generated a src/webpack-cljs/foo.bar.js. 
Same way it would for the module version.

The problem with that is that people may start writing npm packages in CLJS 
where each package would contain its own version of cljs.core. That would be 
really really bad.

Ideally I want
src/index.js
src/foo.js
src/foo/bar.cljs

but have not figured out how to do that yet. webpack has a ton of mutable state 
all over the place so trying to figure out what is going on is not that easy.

I'll probably write the simple version today and see how things work out.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: Any chance we can fit ClojureScript into Webpack ecosystem?

2017-05-12 Thread Thomas Heller

> However I think it's not we current have for all ClojureScript users, since 
> it's implemented by yourself based on lein

That is incorrect. It is a pure Clojure library with no dependency on 
leiningen. I just happen to use leiningen and do not know enough about boot to 
create proper instructions for boot.

You can use it via the REPL

BOOT_CLOJURE_VERSION=1.9.0-alpha15 boot -d 
thheller/shadow-devtools:1.0.20170512-13 -s src repl

(require '[shadow.cljs.devtools.api :as cljs])
(cljs/once :build-id)

https://github.com/thheller/shadow-devtools/wiki/REPL

Some ideas in boot don't play too well with the design I have in mind for 
shadow-devtools but you can use it just fine.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: Any chance we can fit ClojureScript into Webpack ecosystem?

2017-05-12 Thread Thomas Heller
I wrote some things down here:
https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-the-browser#productionrelease-builds

Code splitting is done by the :modules, whether or not you want to use the 
loader is up to you. I personally don't but that is because I have a rather 
traditional website that actually has different pages and I can determine which 
modules are needed based on the page. If you have an actual SPA you probably 
want to use the loader.

:module-hash-names and :bundle-foreign are the caching bits. I just added the 
:module-hash-names since that was still in my private build config, but that 
was in use for about 3 years.


I had an idea for webpack, I'll let you know if it works out.


On Friday, May 12, 2017 at 1:46:32 PM UTC+2, Jiyin Yiyong wrote:
> I used ClojureScript for a year. Probably there are tricks from Closure 
> Compiler that I have no idea.
> 
> 
> For the size, I saw some of the sites I often use have large JavaScript 
> size(with Disable Cache ticked):
> 
> 
> weibo.com 1.2M
> 
> 
> Twitter 437K
> teambition.com 1.9M
> 
> 
> 
> I don't think 84k is a very big deal, while it is for smaller websites. 
> Besides, we may cache and sure the cljs.core.js part, we may use Prepack in 
> the future. In my case it's tolerable.
> 
> 
> Today, using tools like https://github.com/facebookincubator/create-react-app 
> and https://github.com/vuejs/vue-cli we almost get long time caching and code 
> splitting with only several lines of code, with assets(images, fronts) 
> bundling out of box. Hard to imagine we sell those people ClojureScript 
> without competitive features.
> 
> 
> It would still be awesome if you can share about code splitting and permanent 
> caching in ClojureScript :)
> 
> 
> On Fri, May 12, 2017 at 4:55 PM Thomas Heller <th.h...@gmail.com> wrote:
> I'm way too biased towards the Closure Compiler and giving that up is simply 
> not an option for me. I am however very interested in making things simpler 
> for everyone.
> 
> 
> 
> https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-node.js-libraries
> 
> 
> 
> This is an example of how I intend to do that for node libraries, ie. 
> something you just require. This actually bundles things up in a UMD format 
> so the same can work for non-node environments. I would happily add a 
> :browser-umd target that solves some of the issues for webpack users.
> 
> 
> 
> https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-the-browser
> 
> 
> 
> I have used the underlying shadow-build for over 3 years now to do 
> code-splitting with permanent caching of generated files (ie. each generated 
> file has a unique name). I also recently added the :module-loader which lets 
> you async load modules on demand.
> 
> 
> 
> Not sure what asset bundling does so no comment on that.
> 
> 
> 
> I can't do anything about the JVM. I have been using it for too long so I may 
> be blind to the issues people are having with it. It isn't that bad?
> 
> 
> 
> I would say there is actually a good solution to the issues you mention. They 
> just aren't available in the "mainstream" tools and I suck at writing 
> documentation. I'm happy to provide examples any time but need help with the 
> writing.
> 
> 
> 
> Coming back to the webpack loader: I have a few ideas how I would write such 
> a thing. The issue I see, and why I don't, is that the end result is bad. 
> CLJS is built very much with the GCL in mind. cljs/core.js is 1.2MB (151KB 
> gzip) unoptimized. One large file is very non-idiomatic npm/webpack. That 
> also does not contain any user code. UglifyJS is able to shorten some of the 
> code but you still keep about 84K gzip'd. To me that is unacceptable.
> 
> 
> 
> Web-targeted JS needs to be optimized as much as possible and currently that 
> means using the GCL. I don't want to create a "simple" solution that 
> sacrifices this just to make dev-time easier.
> 
> 
> 
> I have been CLJS first for too long now to imagine which issues people are 
> having who are webpack first. Happy to discuss ideas or proposals. Maybe 
> there are ways (like the :node-library, :node-script) that could work even in 
> :advanced mode.
> 
> 
> 
> 
> 
> 
> 
> On Friday, May 12, 2017 at 5:57:58 AM UTC+2, Jiyin Yiyong wrote:
> 
> > It would be nice if we can require ClojureScript in JavaScript, and let 
> > Webpack to handle so many issues.
> 
> >
> 
> >
> 
> > For Webpack use cases, I tried to sell ClojureScript to other front-end 
> > developers around me, but saw some problems:
> 
> >
> 
> >
> 
> > * IMPORT

Re: [ClojureScript] Re: Any chance we can fit ClojureScript into Webpack ecosystem?

2017-05-12 Thread Thomas Heller
I'm way too biased towards the Closure Compiler and giving that up is simply 
not an option for me. I am however very interested in making things simpler for 
everyone.

https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-node.js-libraries

This is an example of how I intend to do that for node libraries, ie. something 
you just require. This actually bundles things up in a UMD format so the same 
can work for non-node environments. I would happily add a :browser-umd target 
that solves some of the issues for webpack users.

https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-the-browser

I have used the underlying shadow-build for over 3 years now to do 
code-splitting with permanent caching of generated files (ie. each generated 
file has a unique name). I also recently added the :module-loader which lets 
you async load modules on demand.

Not sure what asset bundling does so no comment on that.

I can't do anything about the JVM. I have been using it for too long so I may 
be blind to the issues people are having with it. It isn't that bad?

I would say there is actually a good solution to the issues you mention. They 
just aren't available in the "mainstream" tools and I suck at writing 
documentation. I'm happy to provide examples any time but need help with the 
writing.

Coming back to the webpack loader: I have a few ideas how I would write such a 
thing. The issue I see, and why I don't, is that the end result is bad. CLJS is 
built very much with the GCL in mind. cljs/core.js is 1.2MB (151KB gzip) 
unoptimized. One large file is very non-idiomatic npm/webpack. That also does 
not contain any user code. UglifyJS is able to shorten some of the code but you 
still keep about 84K gzip'd. To me that is unacceptable.

Web-targeted JS needs to be optimized as much as possible and currently that 
means using the GCL. I don't want to create a "simple" solution that sacrifices 
this just to make dev-time easier.

I have been CLJS first for too long now to imagine which issues people are 
having who are webpack first. Happy to discuss ideas or proposals. Maybe there 
are ways (like the :node-library, :node-script) that could work even in 
:advanced mode.



On Friday, May 12, 2017 at 5:57:58 AM UTC+2, Jiyin Yiyong wrote:
> It would be nice if we can require ClojureScript in JavaScript, and let 
> Webpack to handle so many issues.
> 
> 
> For Webpack use cases, I tried to sell ClojureScript to other front-end 
> developers around me, but saw some problems:
> 
> 
> * IMPORTANT: hard to install JVM. For JavaScript projects, installing 
> Node.js(with npm inside) would be okay. It's very hard for JavaScript 
> developers to pick up JVM and Boot(or Leiningen).
> * IMPORTANT: long time caching and code splitting. We use these features in 
> production for years. But I don't see a good solution in ClojureScript.
> * Async code loading. For large projects some code can be loaded when a 
> router is activated. No good solution found in ClojureScript.
> * Assets bundling. Now we rely on Webpack to do that, result in using 2 tools.
> 
> 
> Not sure if they can be solved if we have a ClojureScript running on Webpack. 
> But there are many compiled-to-js languages support those features in by 
> supporting Webpack already. That's the purpose behind the post.
> 
> 
> Didn't try `node-jre`. I'm guessing we still need to debug JVM stuffs since 
> it's running JVM?
> 
> 
> On Fri, May 12, 2017 at 6:11 AM Shaun LeBron  wrote:
> On Wednesday, May 10, 2017 at 11:45:02 PM UTC-5, Jiyin Yiyong wrote:
> 
> > Already an old boring topic... I'm from JavaScript side and so many people 
> > are building apps with Webpack. And so many of alt-js languages got Webpack 
> > loaders:
> 
> >
> 
> > BuckleScript https://github.com/rrdelaney/bs-loader
> 
> > PureScript https://github.com/ethul/purs-loader
> 
> > Elm https://github.com/elm-community/elm-webpack-loader
> 
> > Fable https://github.com/fable-compiler/Fable
> 
> >
> 
> > Exception:
> 
> >
> 
> > No Webpack for ReasonML 
> > https://github.com/chenglou/reason-react-example/blob/master/webpack.config.js
> 
> >
> 
> > Can we make a loader for ClojureScript?
> 
> >
> 
> > Or how about the possibility? I guess Closure Compiler will get in the why. 
> > But is it possible if I don't use dead code elimination from Closure 
> > Compiler? I know many people need it but seriously no other solutions? And 
> > how much does ClojureScript depend on Closure Library?
> 
> 
> 
> I'm from the JS side as well, so I'm glad to see this question!  Are you 
> imagining something like the following?  We should probably start by 
> imagining why someone would want to require cljs this way and if it would 
> even make sense to:
> 
> 
> 
> ```
> 
> require('cljs!./src-cljs') // return all goog.provided namespaces?
> 
> require('cljs!./src-cljs/foo/core.cljs') // return a single goog.provide 
> namespace?
> 
> ```
> 
> 
> 
> Either way I think it would 

[ClojureScript] Re: Any chance we can fit ClojureScript into Webpack ecosystem?

2017-05-11 Thread Thomas Heller
IMHO the webpack ecosystem and CLJS can live happily side by side, why is it 
important that they know about each other? Good JS interop ensures that both 
sides can interact well.

What would you expect from a loader that you'd be willing to give up the 
Closure Compiler?


On Thursday, May 11, 2017 at 6:45:02 AM UTC+2, Jiyin Yiyong wrote:
> Already an old boring topic... I'm from JavaScript side and so many people 
> are building apps with Webpack. And so many of alt-js languages got Webpack 
> loaders:
> 
> BuckleScript https://github.com/rrdelaney/bs-loader
> PureScript https://github.com/ethul/purs-loader
> Elm https://github.com/elm-community/elm-webpack-loader
> Fable https://github.com/fable-compiler/Fable
> 
> Exception:
> 
> No Webpack for ReasonML 
> https://github.com/chenglou/reason-react-example/blob/master/webpack.config.js
> 
> Can we make a loader for ClojureScript? 
> 
> Or how about the possibility? I guess Closure Compiler will get in the why. 
> But is it possible if I don't use dead code elimination from Closure 
> Compiler? I know many people need it but seriously no other solutions? And 
> how much does ClojureScript depend on Closure Library?

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Automatic map clj to js conversion

2017-04-27 Thread Thomas Heller
That is done by reagent when it interprets the vector created by 
datetime-picker.

Not a CLJS feature.

On Thursday, April 27, 2017 at 10:04:35 AM UTC+2, Jochen wrote:
> Hi…
> 
> for a few days I am evaluating clojurescript/reagent et.Al.. I just got 
> integrated all the bits and pieces like reagent, cljsjs/react-bootstrap and 
> cljsjs/react-bootstrap-datetimepicker.
> 
> Now I got a working configured datetimepicker on the screen with the 
> following code:
> 
> (def datetime (reagent/adapt-react-class js/ReactBootstrapDatetimepicker))
> 
> (defn datetime-picker []
> [datetime {:input-format "MMM DD,  HH:mm:ss"
>   :date-time  (js/Date.)}]
> 
> What I am puzzled about is where the cljs config map conversion to javascript 
> happens.
> I read about #js, clj->js and the like everywhere, but here the map seems to 
> be automatically converted (including kebab to camel case conversion).
> 
> Is this a newer clojurescript feature I did not read about yet?
> 
> Ciao
> 
> …Jochen

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: [ANN] shadow-devtools: simpler CLJS configs

2017-04-05 Thread Thomas Heller
On Tuesday, April 4, 2017 at 6:09:52 PM UTC+2, Shaun LeBron wrote:
> typo: use "dev" instead of "release" for the full blown dev experience:
> rlwrap lein run -m shadow.cljs.devtools.cli/dev script

Thanks Shaun, a typo indeed.

I wrote some more things down in the wiki:
https://github.com/thheller/shadow-devtools/wiki/Using-shadow-devtools
https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-node.js-scripts
https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-node.js-libraries

and of course the most important browser setup I skipped over before
https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-the-browser

I also fixed some smaller issues that may have prevented some things from 
working properly.

The new version is now: [thheller/shadow-devtools "0.1.20170405"]

Cheers,
/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] [ANN] shadow-devtools: simpler CLJS configs

2017-04-03 Thread Thomas Heller
This thing I wrote is getting to a point where it might be useful to someone 
else. It might make your CLJS life a bit easier.

I have been using my own CLJS tooling (shadow-build) for over 3 years now, it 
had some of lein-figwheel's features that I never talked about but frankly 
lein-figwheel was just plain easier to use so I never bothered.

Over the years however I noticed a trend in my projects that bothered me. I 
would repeat all my build configuration at least twice and only change one tiny 
thing. I would have a :dev build with :optimizations :none and a :min build 
with :advanced. Some other things might change as well but the bulk of the 
configuration stayed the same.

So the goal was simple, abstract the configuration stuff to the basics. You 
define the :target and compile this either in :dev or :release mode. The 
:target defines where your build is supposed to run (ie. browser, node-library 
or node-script). :dev then provides some good defaults for development (with 
REPL, live-reloading, source-maps, ...) and :release takes care of everything 
to produce the most optimized build.

The main goal of this was to automate as much as possible and no changes to 
code should be required when switching between :dev and :release.

Say you want to create a node script, something that runs as a standalone node 
process.

{:id :script
 :target :node-script
 :main demo.script/main
 :output-to "out/demo-script/script.js"}

This creates only the file defined in :output-to. You run that file by calling 
"node script.js arg". It will call "(demo.script/main "arg") on startup which 
is a normal `(defn main [& args] ...)` in `(ns demo.script)`. No need to do the 
usual `(set! *main-cli-fn* ...)` or anything else really.

To compile the script in :dev mode you run:
lein run -m shadow.cljs.devtools.cli/once script

To compile the script in :release mode:
lein run -m shadow.cljs.devtools.cli/release script

Or if you want the full blown dev experience:
rlwrap lein run -m shadow.cljs.devtools.cli/release script

This drops you into a REPL that you can use to interact with the running 
process once you start the node process.


If you just want to integrate with some existing node stuff as a library you 
can use this config:

{:id :library
 :target :node-library
 :output-to "out/demo-library/lib.js"
 :exports
 {:hello demo.lib/hello}}

The :exports map specifies which vars should be exported to node.

> var x = require('./lib');
undefined
> x.hello()
hello
'hello'


The caveat of all this is that these default :target configurations (didn't 
mention :browser yet) are based on what I consider "good" setups. That might be 
totally different from what everyone else is doing. There are also some other 
differences to other build tools like figwheel or lein-cljsbuild, which may be 
confusing at first.

So should anyone be interested in this at all I'd be happy about any kind of 
feedback.

You can find some more information here:
https://github.com/thheller/shadow-devtools

I would consider this ALPHA level but I have been using shadow-build for a 
really long time and some of the devtools things for just as long. I just 
re-wrote some parts recently to simplify the configuration bits. It is nowhere 
near the polish of lein-figwheel but it is probably faster and simpler to 
configure. ;)

Cheers,
/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: ClojureScript CSS-in-JS Solutions

2017-03-17 Thread Thomas Heller
On Thursday, March 16, 2017 at 6:55:44 PM UTC+1, rgde...@gmail.com wrote:
> Thanks for pointing me to your library and to the other thread, I'll take a 
> look!
> 
> In general, I disagree that a string-based solution is strictly worse than a 
> map-based solution, since using strings can help the library remain 
> evergreen. If the library can inject strings that use "real" CSS with little 
> or no parsing, it means that it'll be more likely to support new CSS syntax 
> without needing any updates.
> 
> It also means that current CSS syntax weirdnesses such as pseudoclasses 
> (:hover, etc) and queries (@media, @supports) work how you'd expected them to.

It makes more sense to use strings in JS since you can't achieve what I'm doing 
without more work there. JS doesn't have keywords so it can't differentiate 
between properties and selectors in objects as easily.

You will still use strings for selectors so media queries or pseudoclasses just 
work, property values default to strings as well.

But the most important part is: It is all just Clojure code. Your Clojure tools 
just work. You can call functions, you can merge styles from different parts. 
Good luck doing this with strings.

FWIW styled-components adds 20KB (min, gzip'd) since it requires a CSS parser 
at runtime. It's hard to measure shadow.markup due to :advanced but it much 
less than that, probably 10%.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: how to use new data_readers.cljc feature with deftype

2017-02-16 Thread Thomas Heller
On Thursday, February 16, 2017 at 6:40:41 PM UTC+1, Dustin Getz wrote:
> My expectation is the compiler, when it sees `(def foo #DbId [1 2])` will 
> emit javascript equal to `(def foo (hypercrud.types/read-DbId [1 2])`

Your assumption is incorrect. I cannot answer your question since I have not 
used data_readers.cljc in CLJS. I have however used it in Clojure and my one 
and only recommendation is: DON'T!

Don't get me wrong, tagged literals are excellent when it comes to data. Not so 
much for code though. Lets look at two variants of code that achieve the same 
thing:

data_readers.cljc
(ns my.app)

(def foo #Dbld [1 2])

vs. just plain CLJ(S)

(ns my.app
  (:require [hypercrud.types :as t]))

(def foo (t/dbld 1 2))


These both achieve the same thing. However the non-tagged version is self 
contained. It does not need anything else to run. You can eval it in a REPL and 
it will work. You can see which namespaces are involved and which function is 
called.

The data literal version however cannot run without setting up an environment. 
It must read the data_readers.cljc and eval things (at READ time). Have fun 
debugging this. The trouble with this for CLJS is also that you now must teach 
the compiler about all your objects. Since it must learn what code to emit so 
your object can be constructed by the JS runtime.

So my warning is to never use tagged literals for code.

For data you can use the :readers opts in clojure.edn/read-string [1].

CLJS has (cljs.reader/register-tag-parser! "tag" parse-fn) or the same as above 
if you are using tools.reader.


YMMV,
/thomas

[1] https://clojure.github.io/clojure/clojure.edn-api.html

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Ideas on how to change my code to compile faster

2017-02-12 Thread Thomas Heller
You should try adding {:cache-analysis true} to your :ci target. Caching is 
otherwise only enabled for :none. Maybe that helps.

I have not looked at react-native much yet, not sure what special treatment JS 
files need to run in there. shadow-build probably won't help you much in this 
instance.

/thomas


On Saturday, February 11, 2017 at 4:24:01 PM UTC+1, Ben Brinckerhoff wrote:
> Thanks very much for the ideas!
> 
> We are currently using {:optimizations :simple} for this build. All of the 
> times I quoted above excluded the optimization time, however (I could see the 
> compile time due to :verbose + :compiler-stats). We're in the process of 
> switching to {:optimizations :whitespace} (we were looking at :none, but we 
> need to generate a single file, since this is for a React Native project). 
> 
> >  It would help if you could share your build config. 
> 
> Good point! Here is the cljsbuild build
> 
> :ci {:source-paths ["src" "src-ios" "test" "test-ios"]
>:warning-handlers [foo.cljsbuild-util/fail-on-warning]
>:compiler {:output-to "ios/foo/main.jsbundle"
>:parallel-build false 
>:output-dir "target/ci/"
>:optimizations :simple   ; <- we're in the process of changing this to 
> "whitespace"
> ;; Rules for pulling in RN bundle
> :closure-extra-annotations ["generated" "internal"]
>:closure-defines {"foo.app.config.foo_host" ""
>   "foo.app.config.test_QMARK_" true}
>:language-in :ecmascript5
>:foreign-libs [{:file "../build/react-native-dev.js"
>:provides ["react-native"]}
>   {:file "../build/react-requires-dev.js"
>:provides ["react-requires"]}]
>   :externs ["externs.js"]
>   :verbose true
>:compiler-stats true}}
> 
> and our lein profile is 
> 
> :ci {:env {:test-multiplier "0.5"} ; environ variable
>   :jvm-opts ^:replace ["-Xms1024m" "-Xmx1024m" "-server" "-Xss2m"]
> 
> I was unaware of shadow-build - thanks for the idea! I'll take a look.
> 
> Ben
> 
> On Saturday, February 11, 2017 at 1:26:36 AM UTC-7, Thomas Heller wrote:
> > Are you by any chance using anything other than {:optimizations :none} in 
> > your dev build config? 12s seems a bit excessive if you are just doing CLJS 
> > recompiles.
> > 
> > Ensure that your dev build does not use any production build settings. Your 
> > CI server should probably run in production mode though as 12s shouldn't 
> > hurt that much there. Typically when it comes to building larger projects 
> > you want to rely on :none with caching for development. It would help if 
> > you could share your build config.
> > 
> > 
> > If you are feeling adventurous you could try shadow-build if only to get a 
> > more detailed report on where the time is spent. It should be a bit faster 
> > overall as well but not by much. Happy to walk you through an example if 
> > you want to test it.
> > 
> > /thomas
> > 
> > On Friday, February 10, 2017 at 6:15:34 PM UTC+1, Ben Brinckerhoff wrote:
> > > First of all, thanks to everyone for their hard work on Clojurescript and 
> > > related tooling. It’s an incredibly productive and reliable stack to use.
> > > 
> > > I’m investigating ways to speed up compile times for a closed-source 
> > > project. We have about 8000 Clojurescript LOC and 200 Clojure LOC (in src 
> > > and test combined). Some very rough indicators: a fresh compile of our 
> > > test build takes about 60s. A small change to a file with maybe 15 
> > > reverse dependencies takes about 12s using `cljsbuild auto`. We are using 
> > > lein-cljsbuild 1.1.4 and clojurescript “1.9.293”.
> > > 
> > > These times are pretty good, but of course speeding up compiles shrinks 
> > > our feedback loop, both locally and on CI, where we do a number of fresh 
> > > compiles for different builds. As a result, we want to see if there are 
> > > things we can do to our code to speed up compiles.
> > > 
> > > We have turned on the `verbose` and `compiler-stats` flags so we can see 
> > > more information about compile times. We hope to upgrade to 1.9.456 soon 
> > > so we can see per-file compile stats. We also need to investigate 
> > > parallel builds again - we had previously run into bugs here, but I 
> >

[ClojureScript] Re: Ideas on how to change my code to compile faster

2017-02-11 Thread Thomas Heller
Are you by any chance using anything other than {:optimizations :none} in your 
dev build config? 12s seems a bit excessive if you are just doing CLJS 
recompiles.

Ensure that your dev build does not use any production build settings. Your CI 
server should probably run in production mode though as 12s shouldn't hurt that 
much there. Typically when it comes to building larger projects you want to 
rely on :none with caching for development. It would help if you could share 
your build config.


If you are feeling adventurous you could try shadow-build if only to get a more 
detailed report on where the time is spent. It should be a bit faster overall 
as well but not by much. Happy to walk you through an example if you want to 
test it.

/thomas

On Friday, February 10, 2017 at 6:15:34 PM UTC+1, Ben Brinckerhoff wrote:
> First of all, thanks to everyone for their hard work on Clojurescript and 
> related tooling. It’s an incredibly productive and reliable stack to use.
> 
> I’m investigating ways to speed up compile times for a closed-source project. 
> We have about 8000 Clojurescript LOC and 200 Clojure LOC (in src and test 
> combined). Some very rough indicators: a fresh compile of our test build 
> takes about 60s. A small change to a file with maybe 15 reverse dependencies 
> takes about 12s using `cljsbuild auto`. We are using lein-cljsbuild 1.1.4 and 
> clojurescript “1.9.293”.
> 
> These times are pretty good, but of course speeding up compiles shrinks our 
> feedback loop, both locally and on CI, where we do a number of fresh compiles 
> for different builds. As a result, we want to see if there are things we can 
> do to our code to speed up compiles.
> 
> We have turned on the `verbose` and `compiler-stats` flags so we can see more 
> information about compile times. We hope to upgrade to 1.9.456 soon so we can 
> see per-file compile stats. We also need to investigate parallel builds again 
> - we had previously run into bugs here, but I didn’t take the time to 
> investigate more fully.
> 
> Besides total LOC, are there other aspects of code bases that are known to 
> slow down compiles? Perhaps macro expansion (we have a lot of core.async `go` 
> blocks in some namespaces)? Perhaps the complexity of the dependency graph 
> between namespaces? Something else? Has anyone else had experience altering a 
> CLJS code base to improve compile times? Or tweaking compiler flags? 
> `optimization` makes a big difference of course, but for my current 
> investigation, I'm ignoring optimization time.
> 
> Also, I noticed that Clojurescript performance is an idea for the Google 
> Summer of Code 
> https://github.com/clojars/clojure-gsoc-2017/blob/master/project-ideas.md#clojurescript-performance
> 
> “There are many impactful enhancements we would like to make to ClojureScript 
> with respect to both runtime and compile time performance … For compile time 
> enhancements we should examine where parallelization, AST data representation 
> changes, or more aggressive caching of intermediate artifacts may deliver 
> faster development and production build time.”
> 
> I did a quick search of Clojurescript for perf issues on JIRA, but didn’t see 
> anything related to these (apologies if I just missed something obvious!). Is 
> there a list somewhere of open issues that might improve perf in the 
> compiler? Or are those ideas mostly in the “needs investigation” stage?
> 
> Thanks very much!
> Ben

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: CSS in CLJS

2017-02-08 Thread Thomas Heller
I actually spent a whole bunch of time thinking about the tradeoffs. The 
project has not been in production for that long so my experience is a bit 
limited. So for now things are heavy on the theory. I actually just had a fun 
idea last night and wrote to the closure compiler guys just now.

Anyways here is the current state with regards to performance:

CSS is generated by the compiled JS at runtime.

Pros:
- No extra render-blocking  tag to fetch styles
- Dead-code removal also removes unused styles
- JS caching equals CSS caching.
- CLJS representation of CSS is probably smaller than actual CSS in total bytes 
used (ie. less for the user to download, need more data to verify though)

Cons:
- CSS is generated at runtime, this takes time.
For my current project it amounts to about 25ms total, spread out over time. 
Since styles are generated when they are needed, this can mean 5ms now and 20ms 
when the user clicks a thing (maybe never). I have a solution in place to 
generate the styles on the server but that is not dead-code aware (ie. all 
styles are generated, not just the ones you use). Working through some ideas to 
make this dead-code aware.


Cannot really comment on the performance of the CSS selectors, they should be 
faster than nested rules but it is surprisingly hard to find actual good 
benchmarks for this topic. Most of the information I could find is 2+ years old 
and may not be relevant anymore. The conclusion seems to be that the the 
selectors generated by shadow.markup should be ideal.


I can tell you with a bit of confidence that my solution is much faster than 
any other css-in-js solution I looked at (styled-components, fela, aphrodite 
and more I can't remember). Granted some of them are also shipping PostCSS 
which isn't exactly fast and quite heavy on the download size.


I am committed as the fallback has always been to generate the styles on the 
server. If everything else fails you still get a .css file you can use 
normally. So far the client-side story looks promising though. Writing the 
styles in CLJS has lessened my hate for CSS considerably. It is too early to 
tell whether it will accumulate as much waste as traditional methods over time. 
My instinct feels good about it though. Cursive already tells me whether or not 
I'm using an element by just showing me whether a "def" is used or not.

YMMV
/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: CSS in CLJS

2017-02-06 Thread Thomas Heller
On Monday, February 6, 2017 at 7:15:49 PM UTC+1, mynomoto wrote:
> Hello,
> 
> After seeing this message, we extracted a library from work that uses garden 
> and adds the style when the component is rendered (when using React). Code 
> currently lives at https://github.com/guilherme-teodoro/stylish
> 


Cool, looks very much like

https://github.com/cssinjs/jss
https://github.com/css-modules/css-modules

Great to see some more work on this topic, feels like JS world has been on this 
for much longer. CLJS definitely needs to catch up here.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: CSS in CLJS

2017-02-06 Thread Thomas Heller

> 
> Thanks got it. My mistake was mixing reagent's markup with yours. Would you 
> say this is an alternative, similar to how shadow.markup relates to om.dom?

Yes. While I like the hiccup-ish reagent syntax it does present some 
performance issues.

In reagent you first allocate a bunch of vectors, these are then interpreted by 
reagent and turned into ReactElements allocating even more objects. The vectors 
are now "garbage" and have to be collected. The reagent approach produces about 
twice as much garbage and is slower overall (keyword parsing) as you have way 
more work being done each render, since browsers are pretty fast these days you 
don't notice this much but the price is there.

om.dom or shadow.markup directly go through React.createElement and the result 
will then be interpreted by React effectively skipping the "vector-phase". I 
even go a little further than om.dom if you look at the shadow.markup.react ns 
(direct drop-in replacement btw). I do some macro magic to further reduce cost. 
This is probably overkill though, but you get the usual dom/h1, dom/div, etc 
functions.

I think the reason why the hiccup syntax is so popular is because of the 
shorthand form of :div.class-a.class-b, but since you do not need this with 
defstyled the argument for the hiccup syntax is weaker.

So yes, the hiccup-ish syntax is an alternative but I stick to exclusively 
using the fn-style syntax. Using Cursive indent-only mode it indents just like 
vectors and after doing this for a while now it looks better than the hiccup 
syntax to me. The price of reagent is that you cannot mix both syntaxes, on the 
clojure version I currently support the mixed style but that is probably going 
away at some point.

Sorry, didn't want to turn this into a rant on reagent.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: CSS in CLJS

2017-02-05 Thread Thomas Heller
> Cheers Thomas. When you have the likes of a containing element. How do you 
> handle the wrap when defstyled returns a ReactElement?
> 
> (defstyled container :div
>  [_]
>   {:display "flex"})

Not sure I understand the question? ReactElements can have children, which this 
fully supports.

(defstyled things :div
  [_]
  {:display "flex"})

(defstyled thing :div
  [_]
  {:flex 1
   "&.wide"
   {:flex 2}})

(things {}
  (thing {} "one")
  (thing {:classes ["wide"]} "two")
  (thing {} "three"))


If you are talking about styles that should only apply when B is contained in A 
you can do this

(defstyled A :div
  [_]
  {})

(defstyled B :div
  [_]
  {:normal "styles"
   A
   {:inside-a "styles"}})

I just relaxed the requirements for nesting a bit, previously you had to wrap 
it in a vector and supply a suffix.

(defstyled B :div
  [_]
  {:normal "styles"
   [A ""]
   {:inside-a "styles"}})

But with [thheller/shadow-client "1.0.183"] you can do the above version 
without the vector.  The suffix is so you can refer to parent selectors as well.

I have used this once in my project

(defstyled control-group :div
  [_]
  {:margin-bottom 20
   "&.inline"
   {:display "flex"}

   "&:last-child"
   {:margin-bottom 0}
   })

(defstyled control-label :div
  [_]
  (css/root
{}
(css/rule "&.select"
  {:line-height 37})
(css/rule "&.bold"
  {:font-weight "bold"})
(css/nested-rule [control-group ".inline"]
  {:flex 1})))

(css/...) is the little more verbose syntax, which the maps desugar too. Could 
have used a map, wrote that before I had the map syntax.

The result of this is (assuming "test" ns):

div.test--control-group {...}
div.test--control-group.inline {...}
div.test--control-label {...}

;; and the nested rule:
div.test--control-group.inline div.test--control-label {..}

Hope that answers your question.

/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: CSS in CLJS

2017-02-04 Thread Thomas Heller
Just define them inside the element.

(defstyled h1 :h1
  [_]
  {:color "red"
   "@media (max-width: 600px)"
   {:color "green"}})

Or put the query inside a def, so you can re-use it.

https://github.com/thheller/reagent-test/blob/1dd4193273984971fd1f8fb9717d804a475785af/src/reagent_test/core.cljs#L5-L12

Alternatively you could use the CSS env as well.

(css/set-env!
  {:media
   {:smartphone
"@media (max-width: 400px)"}})

(defstyled h1 :h1
  [env]
  {:color "red"
   (-> env :media :smartphone)
   {:color "green"}})

I'm not too happy with the set-env! call as it must be called before the first 
element is USED (not defined). I call this in my app/init function. Didn't talk 
too much about env yet, but that is basically it. Define anything you want in 
env, it is passed into every defstyled when the first element is created and 
can influence your CSS that way (ie. theming support for re-usable components).

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: CSS in CLJS

2017-02-03 Thread Thomas Heller
FWIW I did a quick test to see if things worked with reagent. Turns out they do.

Basically works out of the box:
https://github.com/thheller/reagent-test

The dependency on Clojure 1.9 was not intentional and I would remove it if 
anyone wants to use this with 1.8.

Anyways feel free to clone the test project and mess around, you get the whole 
figwheel experience + CSS without editing CSS files.

/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: CSS in CLJS

2017-02-03 Thread Thomas Heller
As I said I haven't used garden, can't say how much of a difference there is. 
One thing I can't change is that selectors have to be strings, they are 
keywords in garden. The maps of css properties should be portable though and 
you shouldn't really need the selectors after?

As for re-using css classes: Don't! That is the whole point of this, as 
mentioned here: http://mrmrs.io/writing/2016/03/24/scalable-css/ and elsewhere.

I have been in this situation many times where I'm scared to touch an existing 
class since I have no direct record of who uses it in which situation. Or where 
I added another class with !important, just to have a quick fix somewhere. Also 
I hated OOCSS with things like  where 
the actual order mattered and I never could remember which it was.

You can and should however abuse all the power of Clojure. I have this for some 
of my styles:

(defn button-style [env]
  {:padding 10
   :border (str "1px solid " (-> env :colors :border))
   :background-color (-> env :colors :bg)})
   
and then re-use this a couple time for anything that should look like a button:

(defstyled link :a
  [env]
  (merge
(button-style env)
{:display "inline-block"
 :text-decoration "none"}))

(defstyled button :button
  [env]
  (merge
(button-style env)
{:you-get "the-idea"}))

I currently still have a base.css which includes normalizr.css and some other 
generic classes, you can of course still use (button {:className "generic"} 
...). Nothing wrong with that.


As for performance: The generated selectors are very specific in that they only 
match one thing, too open generic styles tend to cause issues. Also if you 
stick to "modern" things (flexbox) the need for some filler HTML elements goes 
away which improves overall performance, not just CSS. Style generation also 
happens ONCE, so even complex style-fns should not be an issue ever.

Also thanks for :advanced optimizations the code to generate the CSS should by 
much smaller than any actual minified CSS. Did I mention dead code removal yet? 
;)

But I currently have only 89 "defstyled" things in my project myself, as this 
is still fairly new. Too early to make general claims about performance, but it 
should probably be on par with hand-written CSS. Generating styles on the 
client might be a bad idea too, my stuff is not yet complex enough to say. Time 
will tell, I am committed however as the past few weeks produced basically zero 
headaches about CSS and that is a nice feeling.

/thomas


-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] CSS in CLJS

2017-02-03 Thread Thomas Heller
I looked at garden but never used it. It seems like a direct alternative to 
SCSS/Less, but nothing more.

The intent of shadow.markup (sorry, couldn't think of a better name yet) is 
that I basically never want to write a single selector ever again. There are 
several cases where this is still needed but way less than I usually do.

You get several things for free by combining the actual HTML Tag with its CSS.

This is a pretty good introduction to the topic of css-in-js and 
styled-components for React
https://www.youtube.com/watch?v=19gqsBc_Cx0

My API is very much inspired by this library, although less strings and more 
Clojure. There are many more implementations of this here: 
https://github.com/search?q=topic%3Acss-in-js=Repositories

Let me try with some sample Clojure code. You'd write something like this to 
generate a simple html snippet:

(ns my.site
  (:require [hiccup.page :refer (html5))

(defn page-html [title body]
 (html5
  [:head]
  [:body
   [:div.box
[:h1.box__title "foo"]
[:div.box__content body]]]))

Here we invented tree css classnames that we need to remember here and 
whereever we get the actual CSS from. This over time leads to this: 
http://mrmrs.io/writing/2016/03/24/scalable-css/ at least it did for me in just 
about every project ever. Garden does not do anything in this regard I think, 
you still define things in two different places.

With shadow.markup you do this:

;; put all defstyled elements in a separate namespace in a .cljc, so you can 
use it everywhere.
(ns my.html.box
  (:require [shadow.markup.css :as css :refer (defstyled)]))
  
(defstyled box :div
 [env]
 {:padding 10
  :border "1px solid green"})

(defstyled title :h1
 [env]
 {:color "red"})

(defstyled contents :div
 [env]
 {})

;; my/site.clj
(ns my.site
  (:require [my.html.box :as box]
[hiccup.page :refer (html5))

(defn page-html [title body]
  (html5
[:head]
[:body
 (box/box {}
  (box/title {} title)
  (box/contents {} body)))
]))

You do not need to remember whether to use a :h1 or :div, you just directly use 
the elements. Since everything in CLJ(S) is namespaced we get a safe naming 
scheme for CSS classes for free as well. You just write normal CLJ(S) code, you 
don't need to context switch and synchronize the class names back and forth. 
Refactoring the defstyled name in Cursive will rename all of its uses as well 
the CSS classnames. The CLJS version with :advanced gives you dead code removal 
for free, so if you don't use an element it's CSS will be removed as well.

There are many more things but the basic idea is to bundle the CSS with the 
HTML that uses it while still supporting all of CSS (ie. no inline styles) and 
remaining pure Clojure.

HTH,
/thomas





-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] CSS in CLJS

2017-02-02 Thread Thomas Heller
Hello,

I'm not sure how many of you are in this horrible situation where you have to 
write CSS for your React Components. I typically have to write way more than 
I'd like and always hated the way I wrote it. Until a few weeks ago.

I wrote this thing and so far I really like it. Too early to tell whether this 
is actually a good idea but I already prefer it over pretty much everything 
else I have used in the past (CSS, SCSS, OOCSS, BEM, ...).

Anyways here it goes:

(ns my.fancy.component
  (:require [shadow.markup.css :as css :refer (defstyled)]))

(defstyled title :h1
 [env]
 {:color "red"})

(h1 {} "hello world")

In Clojure this produces hello 
world. There are also ways to generate the appropriate CSS so the element 
is actually styled in your page. Not totally settled on the final API but it 
works well enough for now.

In ClojureScript this produces a ReactElement and should work with React 
natively and most CLJS React Wrappers like OM (although I tried no other than 
my own). No extra CSS generation is required here, just include it in your page 
and it will be styled.

More here: https://github.com/thheller/shadow/wiki/shadow.markup

This is basically my take on the whole css-in-js thing that is happening in the 
JS world if anyone follows this. I wasn't happy with any of their 
implementations so I wrote this.

If you'd like to use this try it with this:

[thheller/shadow-client "1.0.180"]

The Clojure part also requires hiccup, the CLJS parts require React via 
cljsjs.react.

If anyone is actually interested in this I'd be happy to go over some more 
details. I just open-sourced this as I wanted to use it in another project and 
needed a place to put it. Consider this very ALPHA though, you have been 
warned. ;)

Cheers,
/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Are multimethods 'expensive' in light of dead code elimination?

2017-01-21 Thread Thomas Heller
You are correct, no defmethod is ever removed by Closure (and can't be really).

You can use :modules to spread them into multiple files, whether or not that is 
useful depends on your project. Protocols are Closure-compatible and might be 
an alternate solution if you are worried about code size.



On Saturday, January 21, 2017 at 8:25:06 AM UTC+1, Ikuru Kanuma wrote:
> Say I have
> 
> (defmulti foo :a)
> 
> (defmethod foo :key1 [arg] (str "key1"))
> (defmethod foo :key2 [arg] (str "key2"))
> ...
> (defmethod foo :key1000 [arg] (str "key1000"))
> 
> Scattered across couple of namespaces in a project.
> Since the dispatch relies on runtime data, I am imagining dead code 
> eliminating the unused ones are difficult, and if that is the case want to 
> know whether it is a good idea to include a large body of defmethods in a 
> single library, or it is better to serve them as a separate library.
> 
> Sorry if this question has been already asked / the question is unclear.
> 
> Thanks!
> 
> Ikuru

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Why is each closure library namespace in a separate js file?

2017-01-21 Thread Thomas Heller
I had a similar idea a while back which I called "compact" mode. It would just 
concatenate all files into one big JS file that would be included in the page. 
To my surprise this wasn't much faster. Turns out that loading a 6MB JS file 
(:none) is not much faster than loading 50+ smaller files. Browsers are pretty 
good at loading things in parallel.

However your idea intrigued me and I implemented it in shadow-build [1]. I see 
only a very tiny gain in overall performance (1.7s vs 1.9s load time). I am not 
using much of Closure though so YMMV. What is a bit annoying though is the 
source-map issue (same reason I eventually abandoned "compact"), by which I 
mean that you'll no longer get an error in "goog/some/thing.js line:30" but 
"my.js line:51234". You could generate a proper source-map for all of it I 
guess but I'm not sure it is worth the trouble (and adds considerable compiler 
overhead).

Long story short: The "download" may actually not be the slow part, executing 
"hundreds of closure library files" might be. Are you sure that you need to 
load all of them all the time?

Are you using :main? Have you tried :modules? Both potentially limit the files 
you need to load.

I'm happy to walk you through shadow-build if you really want to test this for 
your project.

Cheers,
/thomas

[1] 
https://github.com/thheller/shadow-build/commit/c06fd6544cee5605d0ba8e32a1114919102a10bd





On Friday, January 20, 2017 at 5:09:54 PM UTC+1, Justin Ratner wrote:
> We have a fairly large project in which we require a good bit of closure 
> library functionality. While developing with :optimizations :none, hundreds 
> of closure library files are loaded when the page loads. This means that the 
> page takes 7-10 seconds to load. That doesn't seem like much, but when you 
> are refreshing the page many times while developing (I don't always trust 
> code-reload), it adds up.
> 
> Most of the time is spent waiting for browser connections to open up, so the 
> next file can be downloaded. Most browsers can only download a handful of 
> files from one domain at once.
> 
> Wouldn't it be better if the closure library was served in a single js file?

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Deployment Best Practice - Advanced mode vs multiple js files.

2016-11-25 Thread Thomas Heller
Hey,

agreed on external libraries as a rarely changing framework.js served 
separately.

While you are still developing you could do :simple but again that needs to be 
done for everything then. You can't do cljs.core as :simple and the rest as 
:advanced. Too much of the cljs internals rely on either everthing running 
through advanced or nothing. You can't just write externs for cljs.core and 
treat it as an external library. Well you maybe could but you might as well 
skip :advanced at that point.

I would recommend to not worry about it too much while prototyping. Once 
everything settles you probably won't deploy that frequently and given the size 
of well optimized CLJS builds we are probably talking about 100kb (gzip'd) 
which shouldn't really be significant for an enterprise user. Enterprise users 
send around Excel/Word files 10x that size much more frequently. ;) 

You could probably try :simple + closure modules to increase the chance of 
cache hits while developing but in the end you are probably optimizing the 
wrong thing. No one notices 100kb on an enterprise network. Everyone notices 
animations not running smoothly or otherwise janky app performance. Everyone 
says React is fast but it really isn't. I would worry much more about the apps 
performance while running not while downloading. Even :adcanced only buys you 
maybe 5% here.

/thomas



On Thursday, November 24, 2016 at 6:48:41 PM UTC+1, Scott Klarenbach wrote:
> Thanks a lot for the response Thomas.  I think we are on the same page, I 
> just wasn't using the correct terminology.
> 
> I can use :advanced mode for my own code so long as I include an externs file 
> for jquery, material-ui, etc.  
> 
> Not including the external libraries as part of the build (my framework.js) 
> is what you're proposing, and the same goal I was after.  Even with cljsjs, I 
> was including those in the build, and therefore redeploying a 500k+ js file 
> every time a tiny part of my application code changed.  If I remove all non 
> cljs/closure code from the build and just use a cdn and externs, much of my 
> code base doesn't have to be redeployed when my application changes, which is 
> my goal.
> 
> For context, I'm building heavyweight web apps, for a small number of 
> enterprise users.  The code changes rapidly in the beginning due to the 
> prototyping process.  Most traffic is from existing users, not new visitors 
> to a website.  I just wanted a way to return 304s for most of the javascript 
> and only send my app.js code when it changes.
> 
> My instinct is that even the cljs/closure runtime could be deployed to my 
> clients once, and only updated a few times a year.  Hence the idea of simple 
> optimizations.  I think you're saying that I should just resend all the 
> cljs/closure each time with :advanced optimizations.  It just seems to me 
> that in my situation I *could* treat the cljs/closure core runtimes the same 
> way I do jquery - deploy a :simple version once to the client, and rarely 
> have to send again.  Even in :advanced mode, a lot of redundant cljs/closure 
> code is resent to the client each time any tiny part of my app.js changes.
> 
> Thanks,
> Scott.
> 
> On Wednesday, November 23, 2016 at 5:12:15 PM UTC-8, Thomas Heller wrote:
> > Hey,
> > 
> > I have done quite a few experiments over the years and these would be my 
> > general recommendations.
> > 
> > TL;DR: Embrace :advanced fully, keep non-cljs/closure out of your build, 
> > mind your dependencies, use closure modules to split code. 
> > 
> > Most things really depend on your app and your general audience. Say you 
> > have mostly new users that spend some time on your site but only once every 
> > few days/weeks at most. Their cache will very likely be empty most of the 
> > time. So having a "larger but re-usable" framework.js is just worse since 
> > they have to download it anyways. Only because you say "cache forever" does 
> > not mean the browser will do so, some (especially mobile) Browsers will 
> > purge on their own terms (LRU, LFU) anyways to save space.
> > 
> > You can use things like React via a public CDN to increase the chances of 
> > the user having the thing cached. I have no statistics here but in theory 
> > this is a good idea (and fairly common).
> > 
> > You want to keep things like React and Material-UI completely out of your 
> > CLJS build anyways since the Closure compiler doesn't unterstand them and 
> > can't do much. If you get Material-UI via CLJSJS for example it is one huge 
> > JS file, even the min is 150kb gzip'd + 100kb for the icons. If you only 
> > use 3 out of the 40 or so Components they provide you are better off with 
> > JS tools to handl

[ClojureScript] Re: Deployment Best Practice - Advanced mode vs multiple js files.

2016-11-23 Thread Thomas Heller
Hey,

I have done quite a few experiments over the years and these would be my 
general recommendations.

TL;DR: Embrace :advanced fully, keep non-cljs/closure out of your build, mind 
your dependencies, use closure modules to split code. 

Most things really depend on your app and your general audience. Say you have 
mostly new users that spend some time on your site but only once every few 
days/weeks at most. Their cache will very likely be empty most of the time. So 
having a "larger but re-usable" framework.js is just worse since they have to 
download it anyways. Only because you say "cache forever" does not mean the 
browser will do so, some (especially mobile) Browsers will purge on their own 
terms (LRU, LFU) anyways to save space.

You can use things like React via a public CDN to increase the chances of the 
user having the thing cached. I have no statistics here but in theory this is a 
good idea (and fairly common).

You want to keep things like React and Material-UI completely out of your CLJS 
build anyways since the Closure compiler doesn't unterstand them and can't do 
much. If you get Material-UI via CLJSJS for example it is one huge JS file, 
even the min is 150kb gzip'd + 100kb for the icons. If you only use 3 out of 
the 40 or so Components they provide you are better off with JS tools to handle 
this. Webpack or Rollup are supposed to be good and will most likely provide 
better results until Closure fully understands this.

CLJS/Closure code should always go through :advanced though as the potential 
savings are huge and you get better performance for some things on top for free.

If you have a large site with different sections (ie. landing pages, signup, 
logged-in only, etc) it is best to split the code using closure modules so the 
initial download is smaller/faster and only loading the other stuff when you 
need it. Closure does very good work here to optimize the splits.

There are many more micro tweaks you can do (preloading, async loading, etc) 
but not downloading/evaling code you don't use is probably the single best 
thing you can do. If you say your :advanced build is too large I'm willing to 
bet that probably 75% or more are due to foreign dependencies. Optimize those 
first, even if you just put them in a framework.js. Don't sacrifice :advanced 
though.

HTH,
/thomas



On Wednesday, November 23, 2016 at 8:00:31 PM UTC+1, Scott Klarenbach wrote:
> I'm curious about Clojurescript deployment best practices.
> 
> Even in advanced compilation mode, I'm finding the size my js to be pretty 
> large.  But my application code is quite a small fraction of the total.  The 
> rest is the Clojurescript runtime, React, Datascript, Material-UI components, 
> etc.
> 
> On a daily/weekly deployment basis, only my application code changes.  Yet 
> with the practice of advanced compilation, I have to redeploy a large .js 
> file to the web clients just to update the application code - the majority of 
> the data payload hasn't changed at all.
> 
> What I'm thinking of doing is compiling two .js files in simple mode, not 
> advanced mode.  The first called framework.js would include Clojurescript, 
> React, Datascript, etc.  The second called app.js would just be my 
> application code.
> 
> Now on a daily basis I only have to cache-invalidate a relatively small .js 
> file in order to update the web app.  The framework.js file only needs to 
> update every couple months when I want to bump the library versions.  
> 
> I feel the benefits of no longer re-deploying the Clojurescript runtime over 
> and over outway the limitations of not using advanced compilation mode.
> 
> Am I missing something that makes this a bad idea?  Is anyone else doing 
> something similar?
> 
> Thanks for your help.
> 
> -- 
> Regards,
> 
> Scott Klarenbach
> Invisible Robot Technologies
> invisiblerobot.io
> 
> 604-537-1856
> sc...@invisiblerobot.io
> 
> #515 - 207 West Hastings Street
> Vancouver, BC, V6B1H7
> 
> ___
> To iterate is human; to recur, divine

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] INTERNAL COMPILER ERROR starting with Cljs >= 1.8.51

2016-10-18 Thread Thomas Heller
Just guessing but

com.google.javascript.jscomp.VarCheck$RedeclarationCheckHandler.onRedeclaration(VarCheck.java:380)

This looks like you maybe have another extern somewhere that tries to declare 
the coordorigin property. Might be on Object.prototype.coordorigin as this 
would conflict with Element as well. Do you have many other (not default) 
externs active?

Did you check "lein deps :tree" for any conflicts that may mix up the closure 
compiler deps?

/thomas

On Tuesday, October 18, 2016 at 5:15:18 PM UTC+2, Peter Taoussanis wrote:
> Hi David, thanks a lot for the quick reply!
> 
> Tried sampling a few newer + older versions of 
> `com.google.javascript/closure-compiler` against ClojureScript 1.9.75 without 
> much luck:
> 
> v20160713 - No matching ctor found for class 
> com.google.javascript.jscomp.ES6ModuleLoader
> v20160619 - No matching ctor found for class 
> com.google.javascript.jscomp.ES6ModuleLoader
> v20160517 - No matching ctor found for class 
> com.google.javascript.jscomp.ES6ModuleLoader
> v20160315 - INTERNAL COMPILER ERROR [1]
> v20160208 - INTERNAL COMPILER ERROR
> v20151216 - java.lang.ClassCastException: sun.nio.cs.UTF_8 cannot be cast to 
> java.lang.String [2]
> v20151015 - java.lang.ClassCastException: sun.nio.cs.UTF_8 cannot be cast to 
> java.lang.String
> v20150920 - java.lang.ClassCastException: sun.nio.cs.UTF_8 cannot be cast to 
> java.lang.String
> v20150729 - java.lang.ClassCastException: sun.nio.cs.UTF_8 cannot be cast to 
> java.lang.String
> 
> [1]: Default for Cljs 1.9.75
> [2]: Default for Cljs 1.8.40
> 
> That is: newer versions seem to fail with "No matching ctor found for class 
> com.google.javascript.jscomp.ES6ModuleLoader" and older versions with "No 
> matching ctor found for class com.google.javascript.jscomp.ES6ModuleLoader".
> 
> For these tests, I'm just using the following Lein config:
> 
> [com.google.javascript/closure-compiler ]
> [org.clojure/clojurescript "1.9.75" :exclusions 
> [com.google.javascript/closure-compiler]]
> 
> Should I perhaps be doing this some other way?
> 
> (No urgency on this btw, happy to keep using Cljs v1.8.40 for now)

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: basic conceptual question: clojurescript & core.async

2016-08-08 Thread Thomas Heller
You can have concurrency without parallelism.

core.async is "A Clojure library designed to provide facilities for async 
programming and communication". Parallelism is just a bonus side-effect, but 
not required or even the goal. Reducers for example have the goal of 
parallelism over concurrency.

http://joearms.github.io/2013/04/05/concurrent-and-parallel-programming.html
https://vimeo.com/49718712

So you don't need 2+ threads for core.async to be useful. Basically it lets you 
write concurrent code without callback hell. You can write code that looks like 
it would block but is converted to something else under the hood.

HTH,
/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Self-hosting Clojurescript - :context is important

2016-04-26 Thread Thomas Heller
The :context basically tells the compiler if the return value is required 
(:statement vs. :expr). A :statement does not need to return something and "if" 
in javascript does not return something.

If an "if" is compiled with :expr it generates  (condition ? yes : no) instead 
of "if" for :statement.

The compiler assumes :statement as the default for the top-level but when 
working with a REPL that is not the case since you want the result, so :expr 
must be set. The standard cljs repl wraps everything in a pr-str so that 
problem does not show there.

Hope that made sense, but no it is not a bug.

Cheers,
/thomas


On Tuesday, April 26, 2016 at 4:07:12 PM UTC+2, J David Eisenberg wrote:
> Sorry for the bad netiquette of responding to one's own post, but I am 
> wondering if the compile in the condition that doesn't use {:content :expr} 
> is a bug rather than something that should be expected.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: How to make cljs$core$next faster in ClojureScript?

2016-04-21 Thread Thomas Heller
Hey,

the .cirru code looks quite foreign but I guess I can kinda see what is going 
on. cljs$core$next is probably not what is slow here, next when working on a 
lazy seq will realize the next entry. So while next is fast the actual work 
that happens is "slow". Flame Graphs are generally better for understanding 
what is going on.

Anyways, some general recommendations:

- do not profile in dev mode. compile with :advanced mode. use :pseudo-names 
true so you can still kinda see what code is running. At the very least compile 
with :static-fns true.
- do not use partial. quamolit.alias has a bunch which I assume are called 
frequently.
- do not use concat. Too lazy, too many allocations.
- try transducers as well, they allocate less.

HTH,
/thomas




On Thursday, April 21, 2016 at 5:02:28 AM UTC+2, Jiyin Yiyong wrote:
> I got an app with ClojureScript and it's quite slow 
> http://repo.tiye.me/Quamolit/quamolit/
> 
> My code is doing a lot of rendering work, I haven't yet finished designing 
> the caching solution, but the CPU profile showed there's performance issue in 
> `cljs$core$next`. Why is that slow, did I use it wrong?
> 
> My code is at http://github.com/Quamolit/quamolit if you are interested run 
> `boot compile-cirru` to get ClojureScript code, just another syntax... by 
> running `boot dev` to start development environment. Since I used Hit Regions 
> APIs, you need to turn on "Experimental Canvas features" to run the app, 
> check here 
> https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/addHitRegion

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Overview of templates, ways of getting started?

2016-03-22 Thread Thomas Heller
https://github.com/clojure/clojurescript/wiki/Quick-Start

should be done at least once, regardless of whether you are using a template or 
not. It helps clearing up a few things that need to be done in order to get a 
working setup. Templates make you skip this step but it is important to 
understand the moving parts.

Tools like figwheel than add a bunch of (awesome) features on top but all of 
these require options as well. Most of them are targeted at web development and 
fail fast when trying to do something else (ie. node). So we end up with a 
bunch of templates, each trying to do a different thing well and more or less 
ignoring the rest. A one-size-fits-all template would probably be so large that 
no one would understand it.

So my advice would be to not use a template at all. Sure it takes a little more 
time to get up and running but you will understand what each option does and 
why it is there. You will get very fast with this once you have done it a 
couple of times.


Just my 2 cents,
Thomas

On Tuesday, March 22, 2016 at 4:58:47 AM UTC+1, mars0i wrote:
> Clojure: I learn to use Leiningen or boot (in my case only Leiningen), and 
> then I learn Clojure.  Did that.  Love it.  Wrote moderately significant 
> application.  Very comfortable with Clojure.
> 
> Clojurescript: Leiningen or boot, but either way it's more complicated.  OK.  
> Want to get started.  Have gotten started.  Several times.  Made toy 
> examples.  Cool.  But ... still ... puzzled every time I come back to it.  Is 
> my setup a good one?  Where to start over?  Wiki has a total of twelve 
> Leiningen or boot templates.  Each with idiosyncrasies about what has to be 
> installed, how to configure.  (I downloaded this easy template for newbies.  
> Oops have to install X.  Which requires Y )
> 
> These are not complaints--not at all.  I understand that the way in which 
> Clojurescript depends on Clojure requires a few more hoops.  I understand 
> that many people want to use Clojurescript with existing server and 
> Javascript libraries; it makes sense to have various options for different 
> kinds of newbies.
> 
> I'm just wondering whether it could be useful if someone were willing to 
> provide a paragraph or a page of overview advice on the wiki about the 
> options for someone starting out.  "If you want to do this, use that 
> template, but not if you don't care about blah blah."  etc.  This is 
> information that can help a newbie go from the Quick Start page to navigating 
> the Home page of the Wiki.  (Or maybe I just haven't found it yet.)  Not sure 
> how easy this is to do.  By their nature, advice flow charts probably always 
> have exceptions or missing information.
> 
> Thanks!

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: ClojureScript and multi-page website

2016-02-27 Thread Thomas Heller
If you want you can try shadow-build. It supports modules all the way (ie. 
:none). It has some figwheel-ish features (REPL, live-reload) but basically no 
documentation, so a little patience is required. It is pretty simple, just very 
different from other build tools.

See:
https://github.com/thheller/shadow-build
https://github.com/thheller/shadow-build-example

Happy to help if you have any questions.

Cheers,
/thomas

On Saturday, February 27, 2016 at 3:47:34 AM UTC+1, J David Eisenberg wrote:
> On Friday, February 26, 2016 at 5:30:45 PM UTC-8, Francis Avila wrote:
> > And obviously when I said "websockets" above I meant "webworkers"!
> 
> It works just great; thanks. Sadly, it doesn't seem to be compatible with 
> figwheel, as figwheel requires :optimizations :none, but :modules requires 
> :optimizations :simple
> 
> > 
> > 
> > On Fri, Feb 26, 2016 at 7:29 PM, Francis Avila  wrote:
> > 
> > Don't forget the reference documentation: 
> > https://github.com/clojure/clojurescript/wiki/Compiler-Options#modules
> > 
> > 
> > 
> > 
> > On Fri, Feb 26, 2016 at 6:07 PM, J David Eisenberg  
> > wrote:
> > On Friday, February 26, 2016 at 2:52:28 PM UTC-8, Francis Avila wrote:
> > 
> > > I think what you want are multiple Google Closure modules: 
> > > http://swannodette.github.io/2015/02/23/hello-google-closure-modules/
> > 
> > >
> > 
> > > Make a single project for all pages, place each page's entry point into a 
> > > separate namespace and an independent module, and then on each html page 
> > > include the common module followed by the page-specific module. The 
> > > Closure (not cloJure!) compiler will work out the js dependency graph and 
> > > move code among the files optimally so you only have as much javascript 
> > > per page as you need.
> > 
> > >
> > 
> > > This technique also works great with websockets: have browser-thread 
> > > entrypoints in their own module and websocket entry points in another 
> > > module. If you make sure the websocket entry points can't reach code that 
> > > uses browser objects (like document or window) everything will Just Work.
> > 
> > 
> > 
> > Thank you; it seems that this will do what I want, and the article about it 
> > arrived JIT. :)
> > 
> > 
> > 
> > 
> > 
> > >
> > 
> > > On Friday, February 26, 2016 at 3:31:23 PM UTC-6, J David Eisenberg wrote:
> > 
> > > > I'm working on a web site which, for various reasons, achieves its 
> > > > purpose best with multiple pages rather than as a single-page app. All 
> > > > the pages will need to share some code in common.
> > 
> > > >
> > 
> > > > In a plain vanilla JS environment, I could do something like this on 
> > > > page1.html:
> > 
> > > >
> > 
> > > > 
> > 
> > > > 
> > 
> > > >
> > 
> > > > and something similar on page2.html (with 

[ClojureScript] Re: Will advanced optimizations be officially supported on nodejs?

2016-01-25 Thread Thomas Heller
Technically there is nothing holding you back from using :advanced on node, IF 
you supply all externs that is. And this is where the problem lies, you cannot 
easily provide externs since the closure compiler doesn't understand "require" 
properly.

CloSure assumes there is one global namespace that it controls fully and can 
rearrange as it likes. It is called whole program optimization after all. In 
node however each module has it's own little world it lives in and the use of 
global is discouraged. Most node modules usually are not part of the 
optimization either. The current strategy of require/UMD/ES6 module support in 
closure involves rewriting them to look like closure modules, this still has 
the requirement that it requires all code. Someone would still need to write 
externs for all modules that ship with node though.


However, you can cut down the size of :simple by a bit if you also use the 
flags you have for your :advanced build. 

(cljs.build.api/build "src" 
  {:main 'hello-world.core 
   :output-to "simple.js" 
   :optimizations :simple 
   :optimize-constants true 
   :static-fns true
   :pretty-print false
   :target :nodejs})

static-fns and optimize-constants are implicit for :advanced btw, you only need 
to specify them for :simple.

Depending of what your hello-world.core looks like :advanced may have 
eliminated almost everything. Which means you are comparing Apples and Oranges 
since most real world programs wont eliminate this much.



TL;DR: No, it is unlikely :advanced will be officially supported. If you 
compare programs that do actual work the difference will be much smaller and 
startup time usually becomes much less of an issue (if you can even call it an 
issue really).

HTH,
/thomas


On Monday, January 25, 2016 at 6:11:44 AM UTC+1, Roc King wrote:
> Hi all!
> 
> It seems unclear from the quick start wiki page[1]. But in Clojurescript 
> Unraveled[2], it says that :optimizations :none is *mandatory* for nodejs.
> 
> Can we relay on advanced optimizations when targeting nodejs(currently or in 
> the future)?
> 
> Thanks in advance.
> 
> 
> Some reasons(other than runtime performance) to use advanced optimizations:
> 
> . fast startup time and small memory footprint
> . easy to deployment
> . hard to reverse engineering
> 
> without them, clojurescript + nodejs are not so attractive than clojure + jvm.
> 
> 
> The hello world program from the quick start wiki page will take half a 
> second without optimizations:
> 
> $ env time -f '%E %M' node none.js >/dev/null
> 0:00.50 232320
> 
> It is 4x slower and uses 4x memory than the empty nodejs program:
> 
> $ env time -f '%E %M' node  0:00.13 59264
> 
> and is worse than clojure-jvm plus some tweaks for options:
> 
> $ env time -f '%E %M' java -jamvm -XX:+TieredCompilation 
> -Xbootclasspath/a:$HOME/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0.jar
>  clojure.main - <<< '(println "hello clojure-jvm")' >/dev/null
> 0:00.50 175024
> 
> And how could we deploy those things?
> 
> $ du -shc none.js out
> 4.0K  main.js
> 2.7M  out
> 2.8M  total
> $ find none.js out -type f | wc -l
> 26
> 
> Without dead code removal, it will be even worse for non-trival programs.
> 
> 
> :optimizations :simple will solve the deployment problem and will reduce 
> startup time and memory footprint. But it is still 2x slower and uses 3x 
> memory than the empty nodejs program:
> 
> $ env time -f '%E %M' node simple.js >/dev/null
> 0:00.30 174912
> $ du -sh simple.js 
> 708K  simple.js
> 
> And there are some bugs(timeout in core.async, in particular) under simple 
> optimizations. Again, there is no dead code removal in simple optimizations. 
> The Library Problem[3] still exists in clojurescript + nodejs.
> 
> 
> Under advanced optimizations, it will use 1.2x time and memory:
> 
> $ env time -f '%E %M' node advanced.js >/dev/null
> 0:00.16 73552
> $ du -sh advanced.js
> 84K   advanced.js
> 
> With the help of dead code removal, we paid for what we actually use.
> 
> 
> The hello world program and the build options are the same as in the wiki 
> page[1]:
> 
> (ns hello-world.core
>   (:require [cljs.nodejs :as nodejs]))
> (nodejs/enable-util-print!)
> (defn -main [& args]
>   (println "Hello world!"))
> (set! *main-cli-fn* -main)
> 
> (cljs.build.api/build "src"
>   {:main 'hello-world.core
>:output-to "none.js"
>:target :nodejs})
> 
> simple.js and advanced.js are built using the following options:
> 
> (cljs.build.api/build "src"
>   {:main 'hello-world.core
>:output-to "simple.js"
>:optimizations :simple
>:target :nodejs})
> 
> (cljs.build.api/build "src"
>   {:main 'hello-world.core
>:output-to "advanced.js"
>:optimizations :advanced
>:optimize-constants true
>:static-fns true
>:target :nodejs})
> 
> version of nodejs and java are 0.12 and 1.7 respectively:
> 
> $ node -v
> v0.12.9
> 
> $ java -version
> java version "1.7.0_55"
> OpenJDK Runtime Environment (IcedTea 2.4.7) 

Re: [ClojureScript] google closure modules and the :main compiler option

2015-12-08 Thread Thomas Heller
On Tuesday, December 8, 2015 at 12:25:24 AM UTC+1, ewen wrote:
> Would you also consider a patch to make the :main option to accept a 
> collection of namespaces? 

shadow-build is fine with that, expects it in fact. Not really sure why cljs 
allows multiple :entries per :module but :main only allows one. In shadow-build 
everything is built with regards to modules, eg. the typical build with one 
output-file is just a build with one module. How many you add after that is up 
to you. So all options that apply to modules always apply, there is no seperate 
path for modules/non-modules.

Makes things far easier to reason about IMHO.

YMMV,
/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


[ClojureScript] Re: google closure modules and the :main compiler option

2015-12-07 Thread Thomas Heller
You can try shadow-build [1], one of my goals was to make switching between 
dev/prod as simple as possible without requiring any code/html changes. It also 
addresses some other things not related to modules but still helpful to make 
dev/production builds as smooth as possible.

Docs are lacking but I have a few examples [2] that should cover most of the 
things you'd want to do in a build setup. Happy to help if you have questions.

Cheers,
/thomas


[1] https://github.com/thheller/shadow-build
[2] https://github.com/thheller/shadow-build-example

On Sunday, December 6, 2015 at 10:48:22 PM UTC+1, ewen wrote:
> Hi,
> 
> The :main option of the ClojureScript compiler is very useful to be able to 
> leave HTML markup identical between dev and production. However, its purpose 
> is defeated when using google closure modules because it can only output one 
> file and require one namespace.
> 
> A possible solution would be to allow :optimzations :none when :modules are 
> enabled. The compiler would emit multiple main files, each requiring the 
> namespaces it depends on.
> 
> Any thoughts on this?
> 
> Ewen.

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


[ClojureScript] Re: Exporting UMD from ClojureScript library

2015-11-22 Thread Thomas Heller
Hey,

my advice would be to use a post-process step instead of trying to making it go 
through the closure compiler. Not only will that produce headaches but the 
generated CLJS->JS also does not match the expected structure for UMD exports.

You'd need to tag the functions you want to have available by name ala

(defn ^:export js-indent-mode []...)

and then refer to them on the exports. Note that you need to refer to the 
munged names (eg. _ instead of -).

I do not know how to do this in cljsbuild but could show you an example in 
shadow-build if interested. Anyways all you'd need is to pipe the  compiled 
output into the below script (at the marker). No externs needed for this case.

(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.returnExports = factory();
  }
}(this, function () {

// CLJS-COMPILED-OUTPUT-HERE

return {indentMode: parinfer.api_js.js_indent_mode,
indentModeChange: parinfer.api_js.js_indent_mode_change,
parenMode: parinfer.api_js.js_paren_mode};
}));


HTH,
/thomas

On Sunday, November 22, 2015 at 8:42:53 AM UTC+1, Shaun LeBron wrote:
> I'm trying to export a JavaScript API from my ClojureScript library using a 
> UMD pattern, given the following export function:
> https://github.com/shaunlebron/parinfer/blob/7131d10ee21a6674279577b76743f623d4b2c3c9/parinfer-lib/src/parinfer/api_js.cljs#L64-L70
> 
> After compiling in advanced mode, and running Node, 
> `require("./parinfer.js")` just returns {}.  Adding the `:target :nodejs` 
> option doesn't help.
> 
> I'm thinking it has something to do with google closure renaming my `module` 
> symbol despite having the externs to prevent it.  Anyway to prevent this?

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


[ClojureScript] Re: How can I import this foreign lib.

2015-10-30 Thread Thomas Heller
This is very likely to break :advanced optimisations, did you test that yet?

Probably not what you are looking for but there is a "goog.ui.Textarea" [1,2] 
in the closure library which does the auto-sizing as well. Should be pretty 
straighforward to make a react-wrapper for it.

HTH,
/thomas

[1] 
https://github.com/google/closure-library/blob/master/closure/goog/ui/textarea.js
[2] 
https://google.github.io/closure-library/source/closure/goog/demos/textarea.html

On Friday, October 30, 2015 at 12:51:22 AM UTC+1, Leon Grapenthin wrote:
> I solved this by compiling the library to UMD using webpack.  Also, babel is 
> required as a loader to compile ES6 and JS6.
> 
> It might be worthwhile to write a beginners guide about how to deal with the 
> Javascript module world for people who never used JS as their first language. 
>  I'd do it myself but lack expertise. 
> 
> In any case, here is the webpack configuration file I wrote to get the above 
> package to compile so that it can be included via :module-type :commonjs - 
> Your input is very welcome.
> 
> module.exports = {
> entry: "./src/TextareaAutosize.js",
> module: {
> loaders: [
> {
> test: /\.js$/,
> loader: "babel?stage=0"
> }],
> },
> output: {
> path: __dirname + "/dist",
> filename: "result.js",
> libraryTarget: "umd",
> library: "TextareaAutosize"
> },
> externals: {
> "react": {root: "React"}
> }
> }

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


[ClojureScript] Re: How can I import this foreign lib.

2015-10-30 Thread Thomas Heller
Interesting. I might need to try webpack to pre-process files before letting 
closure convert them. I made some attempts including common-js files into a 
build and most of it broke in some way.

I assume you are including react via the normal foreign cljsjs.react?

I don't have a recommended pipeline as the feature simply has not worked for me 
in :advanced.

On Friday, October 30, 2015 at 11:19:25 AM UTC+1, Leon Grapenthin wrote:
> Thanks Thomas for the link regarding the textarea, I might want to try that.
> 
> However I'd be very interested to learn why I should expect that this breaks 
> advanced optimization (luckily it doesn't).
> 
> What is your recommended pipeline? I. e. what module-type should I 
> comp/transpile foreign libs to before adding them to ClojureScript. It seems 
> that webpack is very flexible in that regard so all I'd have to know is what 
> is best for ClojureScript.
> 
> Thanks in advance, Leon.
> 
> 
> On Friday, October 30, 2015 at 9:54:01 AM UTC+1, Thomas Heller wrote:
> > This is very likely to break :advanced optimisations, did you test that yet?
> > 
> > Probably not what you are looking for but there is a "goog.ui.Textarea" 
> > [1,2] in the closure library which does the auto-sizing as well. Should be 
> > pretty straighforward to make a react-wrapper for it.
> > 
> > HTH,
> > /thomas
> > 
> > [1] 
> > https://github.com/google/closure-library/blob/master/closure/goog/ui/textarea.js
> > [2] 
> > https://google.github.io/closure-library/source/closure/goog/demos/textarea.html
> > 
> > On Friday, October 30, 2015 at 12:51:22 AM UTC+1, Leon Grapenthin wrote:
> > > I solved this by compiling the library to UMD using webpack.  Also, babel 
> > > is required as a loader to compile ES6 and JS6.
> > > 
> > > It might be worthwhile to write a beginners guide about how to deal with 
> > > the Javascript module world for people who never used JS as their first 
> > > language.  I'd do it myself but lack expertise. 
> > > 
> > > In any case, here is the webpack configuration file I wrote to get the 
> > > above package to compile so that it can be included via :module-type 
> > > :commonjs - Your input is very welcome.
> > > 
> > > module.exports = {
> > > entry: "./src/TextareaAutosize.js",
> > > module: {
> > > loaders: [
> > > {
> > > test: /\.js$/,
> > > loader: "babel?stage=0"
> > > }],
> > > },
> > > output: {
> > > path: __dirname + "/dist",
> > > filename: "result.js",
> > > libraryTarget: "umd",
> > > library: "TextareaAutosize"
> > > },
> > > externals: {
> > > "react": {root: "React"}
> > > }
> > > }

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


[ClojureScript] Re: My cljs app is too big! Please advise

2015-09-24 Thread Thomas Heller
Are you using whitespace optimization during development? You should really be 
using :none which usually means compilation times in milliseconds.

Do you have any information on the kind of hardware the compile runs on? The 
numbers look horrible. Since you say heroku I imagine a VM in the Cloud which 
usually have very very terrible CPU performance. Do you have numbers from 
actual hardware? (eg. your dev machine)

Other than that it is hard to say more without knowing the project. 259 files, 
38k LOC seems like a lot though and is certainly the largest project I have 
heard of so far.

At 15k LOC my project compiles+optimizes in about 20sec, so 421sec seems really 
high.

Your concerns are valid. Tips for improvements are hard without knowing the 
project, it may just be the hardware but it probably is more than that.

Shameless plug: You could also try shadow-build [1] which can be faster than 
other tools but usually not by _that_ much. I'd be interested on what the 
output of shadow-build looks like though since it provides much more detail.

Cheers,
/thomas

[1] https://github.com/thheller/shadow-build

On Thursday, September 24, 2015 at 10:18:16 AM UTC+2, Yehonathan Sharvit wrote:
> My app is an hybrid app combining angular and om. (old parts of the app in 
> angular, new parts in om)
> 
> 
> 
> 
> 
> My concerns are:
> 1. big app is a symptom of too much complexity
> 2. compilation time on deployment is very long
> 3. compilation time during development is too long
> 
> 
> Any idea how could I improve the situation?
> 
> 
> My app is composed of (not including the dependencies):
> sources: 259 files 38000 lines of code
> 
> 
> Compilation metrics (on heroku)
> whitespace optimization:
> 
> Compile basic sources, elapsed time: 120748.570264 msecs
> 
> Add dependencies, elapsed time: 91876.738647 msecs
> 
> Optimizing 356 sources, elapsed time: 63315.196164 msecs
> 
> Successfully compiled "public/clojurescript/dev/main.js" in 278.23 seconds.
> 
>        
> 
> 
> advanced optimization:
> Compile basic sources, elapsed time: 87952.73688 msecs
> Add dependencies, elapsed time: 81444.699173 msecs
> Applying optimizations :advanced to 353 sources
> 
> Optimizing 357 sources, elapsed time: 251787.456456 msecs
> 
> Successfully compiled "public/clojurescript/prod/main.min.js" in 421.568 
> seconds. 

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


[ClojureScript] Re: "Redirect-after-post" using secretary?

2015-09-12 Thread Thomas Heller
Sorry I got that totally wrong. The XHR actually follows redirects, it just 
doesn't do it like the browser usually does and does not change its location.

The response you are seeing is the final result of the redirect, eg the content 
of /person. You cannot cancel the redirect either as far as I'm aware.

You'll probably need to change the server side response.


On Saturday, September 12, 2015 at 8:53:59 PM UTC+2, Hari Krishnan wrote:
> On Saturday, September 12, 2015 at 2:11:31 AM UTC-7, Thomas Heller wrote:
> > You are using an ajax request which does not follow the same rules as a 
> > normal browser navigation requests. It will not follow redirects for 
> > example.
> > 
> > I don't know what ajax lib you are using but the general solution will be:
> > 
> > fire request
> > wait for response
> > check response code of request
> > if redirect get location header
> > do cleanup of your local app
> > then set document.location.href to location url
> > the page will unload and load /login as "normal"
> > 
> > or you could rewrite the server to not send a redirect but send the 
> > location encoded as data.
> > 
> > HTH,
> > /thomas
> > 
> > 
> > 
> > > 
> > > The response to curl is as follows:
> > > 
> > > HTTP/1.1 302 Found
> > > Server: undertow
> > > X-XSS-Protection: 1; mode=block
> > > Location: http://localhost:3000/login  <-
> > > X-Frame-Options: SAMEORIGIN
> > > Date: Fri, 11 Sep 2015 21:06:28 GMT
> > > Connection: keep-alive
> > > X-Content-Type-Options: nosniff
> > > Content-Type: text/html; charset=utf-8  <
> > > Content-Length: 0
> > > 
> > > However, the reagent form is not getting redirected to he /login form.  
> > > It remains in the same form.  On the console, I can see, however, the 
> > > login page is streamed as an HTML. ( I am using "/login" as just as an 
> > > example.).
> > > 
> > > The original reagent page is doing a request with CLJS-AJAX POST.
> > > 
> > > Any hint is much appreciated.  Thanks,
> > > 
> > > Regards,
> > > Hari
> 
> Hi Thomas,
> 
> Thanks for the answer.  I still have one more issue related to this logic.  
> When I set the :location at the header onn the server side, what I see on the 
> client console (Chrome) is as follows (logging the response from the server): 
>  I don't see the location key/value, instead, I see the whole page in HTML.  
> Any hint?  tried with different doc-types.
> 
> {:status 200, 
>   :success true, 
>   :body "\r\n\r\n\r\n\r\n  \r\n  \r\n  
> --\r\n", 
> 
> :headers {"date" "Sat, 12 Sep 2015 18:27:30 GMT", "x-content-type-options" 
> "nosniff", "server" "undertow", "x-frame-options" "SAMEORIGIN", 
> "content-type" "text/html; charset=utf-8", "connection" "keep-alive", 
> "content-length" "3928", "x-xss-protection" "1; mode=block"}, 
> :trace-redirects ["/person" "/person"], 
> :error-code :no-error, 
> :error-text ""}
> 
> ON THE Client side, I solved the redirect issue with the following code:
> 
> (.assign js/location "/job")
> 
> But I couln't find the location in the header.  So I hard-coded it here!
> 
> Thanks for the response.
> 
> Regards,
> Hari

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


[ClojureScript] Re: "Redirect-after-post" using secretary?

2015-09-12 Thread Thomas Heller
You are using an ajax request which does not follow the same rules as a normal 
browser navigation requests. It will not follow redirects for example.

I don't know what ajax lib you are using but the general solution will be:

fire request
wait for response
check response code of request
if redirect get location header
do cleanup of your local app
then set document.location.href to location url
the page will unload and load /login as "normal"

or you could rewrite the server to not send a redirect but send the location 
encoded as data.

HTH,
/thomas



> 
> The response to curl is as follows:
> 
> HTTP/1.1 302 Found
> Server: undertow
> X-XSS-Protection: 1; mode=block
> Location: http://localhost:3000/login  <-
> X-Frame-Options: SAMEORIGIN
> Date: Fri, 11 Sep 2015 21:06:28 GMT
> Connection: keep-alive
> X-Content-Type-Options: nosniff
> Content-Type: text/html; charset=utf-8  <
> Content-Length: 0
> 
> However, the reagent form is not getting redirected to he /login form.  It 
> remains in the same form.  On the console, I can see, however, the login page 
> is streamed as an HTML. ( I am using "/login" as just as an example.).
> 
> The original reagent page is doing a request with CLJS-AJAX POST.
> 
> Any hint is much appreciated.  Thanks,
> 
> Regards,
> Hari

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


Re: [ClojureScript] Extending protocol to an existing JavaScript type

2015-09-08 Thread Thomas Heller
Hmm I think you have those confused.

Take the equivalent from Java:

class MyClass {
}

MyClass x = new MyClass();
Class y = MyClass.class;

or JS:

var MyClass = function() { /* ctor */ };
var inst = new MyClass()

inst != MyClass
inst.prototype == MyClass

inst is an instance of MyClass (prototype) but not equal to MyClass.

What is going on with Numbers is related to boxing, so there is a perfectly 
fine explanation but that doesn't make it less confusing when you first 
encounter it.

Enough of this, back to topic. Don't extend Native types. ;)

/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


Re: [ClojureScript] Extending protocol to an existing JavaScript type

2015-09-07 Thread Thomas Heller
For a little JavaScript WTF and one reason why things are the way the are:

Number.prototype.whatAmI = function() { return typeof(this); };
var x = 1;
x.whatAmI();
"object"
typeof(x)
"number"

Fun times debugging that ...

Cheers,
/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


Re: [ClojureScript] Extending protocol to an existing JavaScript type

2015-09-07 Thread Thomas Heller


> The point I wanted to make is 'this' without 'new' will refer to the object 
> the function is defined on be it 'window' or whatever object.
> 

That is incorrect. "this" is the actual number, not window. new or not. 
Behavior is probably different for other types. ;)

Number.prototype.addFive = function() { return this + 5 };
var x = 1;
x.addFive(); => 6
var x = new Number(3)
x.addFive(); => 8

Anyways, we agree that JS is full of WTF. Let's enjoy our sweet sweet CLJS 
world. :)

Cheers,
/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: Clojurescript async not yeilding for CPU intensive work

2015-08-26 Thread Thomas Heller
Well, while we are on the topic perhaps we should mention the downside of using 
Web Workers. For me it has been Data Transfer.

Since you can only transfer JSON type data between workers that usually meant 
you had to pr-str/read-string to roundtrip CLJS data. If you only have very 
small amounts of data that is no problem but read-string is not very performant 
and even something like 1mb of data will eat up enough CPU time to drop you 
below 60fps.

That might now be worked around with transit though since that is much faster. 
But still if you need to transfer a lot of data between workers you might be 
better of not using them. IE8/9 might also be an issue but even Microsoft 
suggest that you should not support those versions.

Oh and so far I have not seen support for workers in lein-cljsbuild and I 
haven't documented anything in shadow-build so building web worker javascript 
files might actually be something of a mystery to people. To be honest I never 
used them for anything other than toy projects either.

Anyways, I like them. Use them. It is not that hard. :)

Cheers,
/thomas



 
 Why the cynicism? Isn't it true that the only way to make use of multiple 
 cores in browser is to use WebWorkers?
 


-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: Clojurescript async not yeilding for CPU intensive work

2015-08-26 Thread Thomas Heller
On Wednesday, August 26, 2015 at 1:29:38 PM UTC+2, Daniel Kersten wrote:

 
 If you can use newer browser, you've got Transferrable Object to transfer 
 binary data with zero-copy.
  

True but I was talking about CLJS data which isn't binary.

 
 Agreed, its probably a bit of work. I guess that since each one has its own 
 JS context, the simplest way is probably to have two cljs projects: your main 
 code and your web worker code.
 

Actually you want to use closure modules so some code can be shared. With 2 
projects the client will download 2 separate instances of cljs.core which is 
quite heavy.

I have an example here:
https://github.com/thheller/shadow-build/tree/master/cljs-data/workers/src
https://github.com/thheller/shadow-build/blob/master/dev/build.clj#L6-L30

It is not a good example but the idea is to have one common module (cljs) and 
one for each client (ie. the page itself, worker1 and worker). worker1 (and 
2) will automatically load the cljs module which the browser already has 
available because the page did already load it.

But this is going too far off-topic. If anyone is actually interested in using 
WebWorkers I'd be happy to go into further detail on how that works in 
shadow-build.

Cheers,
/thomas

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


[ClojureScript] Re: Clojurescript async not yeilding for CPU intensive work

2015-08-25 Thread Thomas Heller
This has nothing to do with core.async or the go macro. If you block the CPU 
you will block the UI. The browser does not support threads so neither can 
core.async.

What the timeout achieves is that you give some control back to the browser so 
instead of 1sec blocking you get 5x200ms blocking. Still far from 60fps but 
better than 0.

If you want to do CPU intensive work without blocking the UI you'll need to use 
one or more WebWorkers. You could layer core.async on top of that to 
communicate between the Workers and the UI but core.async itself does nothing 
in that regard.

WebWorkers are pretty easy to get going but carry their own set of drawbacks so 
it is very dependent on your use case whether they make sense or not.

HTH,
/thomas



On Monday, August 24, 2015 at 5:33:48 PM UTC+2, Timothy Pratley wrote:
 I have an issue where work inside a 'go block' is blocking my UI.
 Inserting a (! (timeout 1)) 'fixes' it.
 
 ** Is there a more idiomatic way? **
 
 Here is a cut down version built from a fresh template:
 If you run this code, you don't see the thinking deeply countdown, and you 
 cannot click the other button.
 
 If you uncomment the timeout 1, it works better.
 
 
 
 (defn hello-world []
   [:div
[:h1 (:text @app-state)]
[:button
 {:on-click
  (fn [e]
(swap! app-state assoc :thinking true :thinking-deeply 5)
(go
  (while (pos? (:thinking-deeply @app-state))
;(! (timeout 2000))
(apply * (rest (range 1000)))
;(! (timeout 1))
(swap! app-state update :thinking-deeply dec))
  (swap! app-state dissoc :thinking :thinking-deeply)))}
 The button!]
(when (:thinking-deeply @app-state)
  [:h2 Thinking deeply  (:thinking-deeply @app-state)])
(when (:thinking @app-state)
  [:h2 Thinking])
[:button The other button]])
 
 Full source code is attached
 
 
 Regards,
 Timothy

-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


Re: [ClojureScript] Re: Clojurescript async not yeilding for CPU intensive work

2015-08-25 Thread Thomas Heller
On Tuesday, August 25, 2015 at 10:59:53 AM UTC+2, Daniel Kersten wrote:
 The browser does not support threads so neither can core.async.
 
 
 To expand on that, core.async uses cooperative multitasking, which means you 
 have to give control back every so often so it can schedule other go blocks 
 to be run. Calls like ! will do this while they block (which is why timeout 
 works).
 

While that is correct let me emphasize that timeout is not a solution!

Do you always know how long task X will run or whether you are going to need to 
chunk it? Is it even possible to split up? A task that may complete in 10ms 
on your machine might take 100ms on another one or even 500ms on yours if the 
computer is doing something else.

If you need to do CPU intensive work in the browser use a WebWorker. It is 
their purpose. While not perfect it is far better than trying to be 
cooperative in your code.

My 2 cents,
/thomas



-- 
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 post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.


  1   2   >