Fork me on GitHub
#shadow-cljs
<
2021-07-28
>
borkdude06:07:02

How can I create a Node CLI tool that allows for optional modules, similar to the modules feature?

borkdude06:07:29

I’m not sure if modules are supported for this use case

borkdude06:07:26

Eg I want to offer reagent support, but for those who don’t need it, it should not have to load reagent at startup

borkdude06:07:22

I’ve done something similar for scittle via modules but for a Node CLI, can that work as well?

thheller06:07:54

if you are asking about :node-script then no that cannot do :modules. there is no currently available target for node that would support this

thheller06:07:24

you could write one but its never come up before so it doesn't exist, also much less relevant in node land given that you'll probably save 1ms or so on startup

borkdude07:07:29

Do you mean that loading reagent only takes one more ms?

borkdude07:07:50

I want to make a scripting tool for node and support a variety of libs. Would be very nice if modules worked, so it can be … modular.

borkdude07:07:41

See borkdude/tbd

thheller07:07:31

well did you try a benchmark of loading nothing vs everything? last time I tried it didn't make much of a difference

thheller07:07:42

certainly not seconds like it does in clojure

thheller07:07:27

modular is trivial from the build perspective though. nobody ever asked for it though so it doesn't yet exist

borkdude07:07:30

@thheller I didn't benchmark yet, but can do later today. > modular is trivial from the build perspective though. that sounds cool. Does it work with :node-library already though? I assume it's not that hard to offer a library (which I want to do anyway) that exposes on CLI main namespaces as well

borkdude07:07:07

The benchmark is a bit too early days though: adding just one lib might be ok, but dozens of them might impact startup time, which I want to avoid in the long run

mauricio.szabo15:07:57

I'm trying to use :target :npm-module, but no matter what I do, I always get the error:

module.exports = goog.debug.Error;
                            ^
TypeError: Cannot read property 'Error' of undefined
Am I doing something wrong here?

thheller16:07:43

@mauricio.szabo :npm-module is pretty much dead. some recent updates to the closure-compiler,closure-library makes it pretty much a no-go

thheller16:07:19

been trying to come up with some ideas how to work arround that but so far no luck

thheller16:07:28

@borkdude none of the node targets support modules currently. :target :esm does but that not yet fully working for node since the focus was the browser. also still not sure what the current state of ESM in node is. I think it works but interop with CommonJS is kinda weird

borkdude16:07:37

it's ok, we just need to have the module loaded and it will register itself through some side effect. beyond that we don't really need interop with the module

thheller16:07:59

thats not what I meant

thheller16:07:24

:esm is currently sort of hard coded to bundle all dependencies. which typically isn't what you want for node builds

thheller16:07:41

I mean you can try it, maybe it just works for whatever you are trying to do

borkdude16:07:14

thanks. @mauricio.szabo is trying this :)

borkdude16:07:45

or is this something else than :npm-module? oh I see

thheller16:07:15

:esm is the modern replacement of :npm-module basically yes

borkdude17:07:38

@thheller what I want to do is basically the same as scittle (https://github.com/borkdude/scittle/blob/main/shadow-cljs.edn) but then for the nodeJS ecosystem. Just to give you some context. I understand that things may not be there yet. Will give :esm a go.

borkdude17:07:58

scittle "plugins" are loaded just by including the source in a script tag

thheller17:07:35

I don't know what you mean by "for the nodeJS ecosystem". I don't even see the point of scittle to be honest so I'm unsure what problem you are actually trying to solve

borkdude17:07:49

scittle is a way to make small CLJS apps by just including source in script tags. the use case is to get something going quickly. when the project becomes "too big" then you can migrate to a normal CLJS project.

thheller17:07:23

yeah but why not start a normal CLJS project directly. takes like 10 lines of setup 😛

borkdude17:07:43

I understand that you may not see the point, but trust me, some people do ;)

thheller17:07:01

yeah, I totally realize that I'm not the target audience for this 😛

borkdude17:07:12

I didn't expect you to be

thheller17:07:16

for the esm target you can pretty much re-use your :modules from scittle

thheller17:07:31

hmm or maybe not. I think I made :exports a required thing

borkdude17:07:12

I noticed that when I tried something different before, I think it can just be an empty map

thheller17:07:49

no it calculates the :entries from :exports so its definitely needed

thheller17:07:58

otherwise it won't know which namespaces go where

thheller17:07:10

that should have been additive with :entries but currently isn't

thheller17:07:02

just :init-fn would work though. so no :exports just :init-fn, at least judging by the code 😛

thheller17:07:03

that does a assoc :entries but later merges the :init-fn

thheller17:07:32

but maybe you want :exports anyways, don't know exactly what you are planning for node

thheller17:07:41

I understand the script tags variant but how does it work in node?

borkdude17:07:31

in node it would work similarly: you would always start with the tbd.core "module" and optionally you can then load tbd.reagent for example. on load, that module will register itself in some atom.

borkdude17:07:50

tbd.reagent should be loaded through some js/require

thheller17:07:34

I get that but where does the user put the code?

borkdude17:07:23

the user code is a script which gets loaded from a .cljs file which is then interpreted

borkdude17:07:29

this is also the same with scittle

thheller17:07:51

hmm? scittle looks for <script type="application/x-scittle"> or did I miss something?

borkdude17:07:24

yes, tbd (name is subject to change) exposes one CLI main function which has one argument which is the input file

borkdude17:07:44

so if you run tbd foo.cljs it will run foo.cljs

borkdude17:07:11

and in foo.cljs you can call js/require again

thheller17:07:12

so lumo but sci instaed of self-hosted?

borkdude17:07:20

yes, kind of

borkdude17:07:40

slightly different I would say. not better, different ;)

borkdude17:07:32

so tbd can have multiple pre-compiled libs available that can be optionally loaded, aside from interpreted scripts and npm libs

felipethome19:07:51

Hi! Is there a way to get all declared externs in the command line?

mauricio.szabo19:07:37

@thheller so I was able to make something work with :npm-module, and now I'm migrating to :esm. It's giving me the following error:

file:///home/mauricio/projects/tbd/out/cljs-runtime/shadow.cljs.devtools.client.websocket.js:5
var socket = (new WebSocket(ws_url));
             ^

ReferenceError: WebSocket is not defined
    at shadow$cljs$devtools$client$websocket$start (file:///home/mauricio/projects/tbd/out/cljs-runtime/shadow.cljs.devtools.client.websocket.js:5:14)

thheller19:07:11

@mauricio.szabo need to set :runtime :node in the build config, otherwise it assumes browser

thheller19:07:33

:esm needs some work for node targets. I only tested browser and deno as described in the clojureverse post

mauricio.szabo19:07:48

Right, ok. So far, it works-ish... release don't work (it fails with Error processing externs: JSC_PARSE_ERROR. Parse error. Semi-colon expected at externs.modules.js line 1 : 10)

thheller19:07:07

hmm odd, wonder what that line is? can you check the file in .shadow-cljs/builds/<build-id>/release?

mauricio.szabo20:07:31

This file doesn't even exist...

╰─>$ ls .shadow-cljs/builds/modules/
dev/

mauricio.szabo20:07:09

╰─>$ npx shadow-cljs release modules --verbose
shadow-cljs - config: /home/mauricio/projects/tbd/shadow-cljs.edn
[:modules] Compiling ...
-> build target: :esm stage: :configure
<- build target: :esm stage: :configure (3 ms)
-> Resolving Module: :tbd.core
<- Resolving Module: :tbd.core (226 ms)
-> Resolving Module: :tbd.main
<- Resolving Module: :tbd.main (0 ms)
-> Resolving Module: :tbd.reagent
<- Resolving Module: :tbd.reagent (0 ms)
{:type :empty-module, :mod-id :tbd.main, :shadow.build.log/level :info}
{:type :empty-module, :mod-id :tbd.reagent, :shadow.build.log/level :info}
-> build target: :esm stage: :compile-prepare
<- build target: :esm stage: :compile-prepare (2 ms)
Error processing externs:
JSC_PARSE_ERROR. Parse error. Semi-colon expected at externs.modules.js line 1 : 10
Don't know if it helps

mauricio.szabo21:07:21

Also, if it helps, this is the code that's currently failing to compile: https://github.com/mauricioszabo/tbd/tree/migrating-to-esm