On Sunday, July 9, 2017 at 8:06:00 PM UTC+10, Thomas Heller wrote:
>
> 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.
>


Yeah! :)
 

>
> First we need to split compilation and bundling.
>


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.
 

>
> 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.
>

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. 
 

>
> 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. 
>

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.  


> :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.
>

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.  
 

>
> 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).
>

I don't necessarily agree or disagree on mvn but npm is what modernjs devs 
use and they are familiar with its quirks, maven has its own set of tools 
to troubleshoot dependency conflicts and js devs unfamiliar with java may 
have more difficulty configuring repo authentication and troubleshooting 
the errors.  I would rather deploy to npm, but if compile must happen down 
stream then I think your solution is a pretty good one. 
 

>
> :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. 
>

True a more general tool is probably better than a webpack plugin.
 

>
> 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.
>

Yeah. Hopefully my rambling is useful feedback, your goals are probably a 
bit different than mine and thats okay - its your tool :)  


> /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 are many:
>>
>> * separate download - not bundled with other js libraries
>> * not commonjs / cannot require / pollutes global namespace 
>> * install/upgrade/versioning process is different / change script tag 
>> rather than npm/yarn
>> * each precompiled ClosureScript library will include closure and cljs 
>> again
>>
>> As we add support for multiple editors I want to split the library into 
>> multiple artifacts that can be released separately, however that last 
>> bullet point is undesirable.  I have had some success in adding a cljsbuild 
>> along side a webpack build, but CommonJS has solved a lot of pain points 
>> for JS devs and most modern js devs now expect an npm artifact. 
>>
>> Although shadow-cljs doesn't solve having different install/version 
>> process it does appear to solve the other issues and is better than using a 
>> script tag.
>>
>> I did have a general question though. I understand that if you compile 
>> multiple ClosureScript libraries independently each will end up with 
>> duplicate bits of closure and cljs core. Shadow-cljs, as I understand it, 
>> appears to solve this by first compiling all the ClosureScript code 
>> together and exposing it as a commonjs module. But thinking out-loud 
>> here...isn't sharing dependencies the problem npm is trying to solve? could 
>> we leverage that instead of reinvent it?  
>>
>> What if google closure libraries and cljs.core were published as their 
>> own commonjs npm libraries - precompiled but not minified yet? Couldn't 
>> cljs libraries then just 'require' them without resulting in another copy 
>> or requiring the closurescirpt compiler (and jvm)?  In my ideal world, I 
>> think I would be able to specify :npm-module as the clojurescript compiler 
>> target and it would generate js that can be packaged in npm that 'requires' 
>> rather than bundles cljs and closure.  Minification can be done downstream 
>> with *all* the javascript, not just the cljs code. I also found a closure 
>> plugin for webpack https://www.npmjs.com/package/webpack-closure-compiler 
>> (I never used it though), so maybe we can still get just as good if not 
>> better results doing it later? 
>>
>> I'm not sure what would be involved in rewriting cljs output to require 
>> "require" closure and cljs.core as their own libraries, but maybe the 
>> partially solved already with 
>> https://github.com/clojure/clojurescript/wiki/JavaScript-Module-Support-(Alpha)
>> ?
>>
>> 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 [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/clojurescript.

Reply via email to