Fork me on GitHub
#cljs-dev
<
2018-04-10
>
Garrett Hopper03:04:22

How difficult would it be to allow :target :nodejs projects to have their node modules :optimizations :advanced compiled instead of direct require() statements? Briefly attempting to modify the compiler, it seems like the only hurdle it when built-in node functions are required. Perhaps there's an easy way to do this?

richiardiandrea05:04:23

Funny, I was considering something like that myself, are you running on lamdba? Because that is the only use case I had to shrink the dependencies...it would be great to know yours :)

Garrett Hopper14:04:58

Yeah, I'm using AWS lambda; how'd you guess? 😛 I'd like to have a single set of :npm-deps without having to use the whole node_modules directory for every lambda that doesn't necessarily use all the :npm-deps.

richiardiandrea14:04:21

Ah ah I was thinking exactly the same, then David basically convinced me that it is not worth the trouble.

Garrett Hopper19:04:27

Sorry for the delay. Not worth the trouble in what way? Not worth the trouble to implement it?

richiardiandrea19:04:06

he basically was suggesting that the performance you can squeeze out of that is minimal, I would suggest to ask him directly

Garrett Hopper20:04:20

@dnolen I think there's more to be gained from just performance. Being able to compile everything to a single bundle with a shebang (avoiding node_modules altogether) for node scripts could be very useful. I'm experimenting with doing this with webpack at the moment. Is this a good idea?

john04:04:51

@thheller so here's a basic example of the lazy dep module stuff I was talking about: https://github.com/johnmn3/cljs-main-code-splitting/blob/master/modules/mod_init/main.cljs

john04:04:09

Brought the convo over to #architecture for further discussion

thheller16:04:28

still no idea what your vision is sorry. I stand by saying that using cljs.loader in a library is not a good idea.

john16:04:36

I guess the idea is that modularity should be inheritable by downstream module authors... Sort of like a plugin system.

thheller16:04:58

yeah but you don't know how your client is going to use your code. your :modules config might not make sense for them.

thheller16:04:19

also in your macro solution (one/hi-one "mod-acme") makes it appear like this is an actual sync method that you could use say in (let [x (one/hi-one "mod-acme")] ...) when it actually is an async method doing all kind of stuff.

john17:04:11

Right, it's inherently async on that first call... Prefetching on ns load is another option

john17:04:20

But if that first call happens on ns load, it'll still be async. Well, you could shelve all calls the the module fns during load time, like is sometimes done in JS - that way it'd feel more like normal - and subsequent calls would resolve to the locally loaded var directly.

john17:04:32

But it's still a little hairy in general, yeah.

john17:04:30

and wrt "yeah but you don't know how your client is going to use your code", it may be that this aspect of hot module loading is only feasible in CLJS land, or Closure JS tools that are careful with usage. And, outside of that, it is only useful when defining deployable artifacts to apps.

john17:04:28

I can tell you that at least for the app I'm currently working on - which is a sort of combination between MDC and Google Analytics - this workflow would make development for me much easier - in a mono-repo, decoupled way

thheller17:04:56

apps decide if they want to split or not. split usually occurs at the namespace/import level (but Closure can go deeper). so the best you can do is provide reasonable NS setups so apps can pick what they need.

thheller17:04:43

but ultimately the lib should make no presumption whether a split is used or not. (IMHO)

john17:04:37

well, it my current setup, if you want to use the thing lazily, you go through the loader route by requiring the lazy ns. If you want to use non-code-motion, single-DCE-artifact method, you just require the main ns and call the fn directly through there.

john17:04:49

downstream authors then have the option of consuming my lib via individual modules and then defining their own modules that further downstream users can consume, or they can just consume them directly via their mains

john17:04:32

So, I think I'm not presuming how downstream authors want to consume or provide my modules.

thheller17:04:34

well since cljs.loader is pretty heavily bound to the build config it is. the app must define the exact module name with the exact namespaces and so on.

john17:04:11

indeed, I think so

john17:04:48

Folks wanting to construct a new module will need to define their module layout locally to be fully in tune with upstream module layouts, I believe.

thheller17:04:20

yep. doesn't sound very user friendly. I think using cljs.loader directly is probably easier than using your lazy wrappers

john17:04:29

Still experimenting with it though, to get more clarity around that

john17:04:39

could be

john17:04:46

all these same limitations exist for MDC though, I think. Constructing new components requires a certain degree of integration with their module framework. Feasibly, though, users could make their own MDC components and use them privately, with all the same benefits that Google is getting out of modularized MDC.

thheller17:04:54

you are getting that completely wrong

john17:04:09

Basically, it's like a library extension mechanism, with the purpose of letting downstream app builders define the final module layout.

thheller17:04:13

MDC modules are not what :modules is about. JS/MDC modules are basically namespaces for JS

thheller17:04:15

its very confusing since modules is such an overloaded term

thheller17:04:25

but :modules has nothing in common with ES6 modules

john17:04:58

I'm familiar with the difference between the two senses of modules

thheller17:04:03

:modules and cljs.loader is JS import(...).then(...) not import X from "foo"

thheller17:04:21

there is not a single use of import(...) in MDC (pretty sure about that)

john17:04:12

okay, after rereading: https://material.io/components/web/docs/closure-compiler/ I see they don't mention any code splitting...

john17:04:36

I definitely misinterpreted their situation

john17:04:18

well, whatever, I made the thing and now it's there... And I need the leverage, so I'll continue to explore it a little more 🙂

Garrett Hopper14:04:58

Yeah, I'm using AWS lambda; how'd you guess? 😛 I'd like to have a single set of :npm-deps without having to use the whole node_modules directory for every lambda that doesn't necessarily use all the :npm-deps.

Garrett Hopper20:04:20

@dnolen I think there's more to be gained from just performance. Being able to compile everything to a single bundle with a shebang (avoiding node_modules altogether) for node scripts could be very useful. I'm experimenting with doing this with webpack at the moment. Is this a good idea?