Fork me on GitHub
#shadow-cljs
<
2023-01-30
>
Drew Verlee02:01:41

Will a app re-compile rerun any clj macros that were used to build the intial app state? I'm running into a sitution where i have values that from a previous state that i'm trying to understand.

thheller06:01:58

not if its cached. if you have macros that have side effects you might need to disable cache completely. macros are not supposed to have side effects. https://shadow-cljs.github.io/docs/UsersGuide.html#_compiler_cache

Drew Verlee17:01:15

Thanks heller. Those docs help, and yes, i assume we have macros with side effects.

hifumi12305:01:46

I would say it depends on what files actually changed. If you have a bunch of macros in a util namespace and never change that namespace, then it wont be refreshed. So in that case I can understand the previous state you’re speaking of. If I wanted to make namespaces forcibly refresh every time, I would add the ^:dev/always metadata to them

Andrea12:01:41

Hello shadowians, I’m trying to compile a project which has https://www.npmjs.com/package/squint-cljs as an NPM dependency, and I’m getting the following error when starting the dev build

shadow-cljs - watching build :viewer
[:viewer] Configuring build.
-> build target: :esm stage: :configure
<- build target: :esm stage: :configure (2 ms)
[:viewer] Compiling ...
-> Resolving Module: :viewer
<- Resolving Module: :viewer (1293 ms)
-> build target: :esm stage: :compile-prepare
<- build target: :esm stage: :compile-prepare (5 ms)
-> Closure JS Cache read: 101 JS files
<- Closure JS Cache read: 101 JS files (21 ms)
-> Babel transform: /Users/amantini/dev/clerk-blank/node_modules/squint-cljs/core.js 
<- Babel transform: /Users/amantini/dev/clerk-blank/node_modules/squint-cljs/core.js  (394 ms)
-> Shadow JS converting 1 JS sources
<- Shadow JS converting 1 JS sources (551 ms)
[:viewer] Build failure:
Closure compilation failed with 1 errors
--- node_modules/squint-cljs/core.js:625
Transpilation of 'Computed fields' is not yet implemented.
The offending code seems indeed to be:
export const IIterable = Symbol('Iterable');
...
class LazyIterable {
  constructor(gen) {
    this.gen = gen;
  }
  [IIterable] = true;
  [Symbol.iterator]() {
    return this.gen();
  }
}
https://github.com/squint-cljs/squint/blob/c50c4c2582aeda9e874a867e19a2bfcfc9e4caab/core.js#L452-L460 Does anyone have also encountered this issue before? Couldn’t find much around closure compiler and computed fields or properties. Both targets :browser and :esm produce the same issue, changing :output-feature-set to different ES levels also has no effect

borkdude12:01:50

Why does closure need to transpile anything if it's already es6?

Andrea12:01:07

yeah, that’s also a good question

thheller12:01:24

uhm do not do this?

thheller12:01:11

oh nvm. thought for a sec it was trying to compile the squint cljs output

thheller12:01:32

update shadow-cljs I guess?

Andrea12:01:59

I’m on 2.20.20

thheller12:01:47

hmm ok. then I guess it doesn't work

Andrea12:01:29

> to compile the squint cljs output yeah, that is what I origninally tried to do, and the squint output has imports to squint-cljs/core.js which produces the error above

thheller12:01:58

do not ever include the output of a compiled CLJS lib via JS

thheller12:01:05

that will only bring trouble and nightmares

borkdude12:01:10

squint produces normal JS, not CLJS

borkdude12:01:27

everything is "just es6" - imo closure should be able to handle this

thheller12:01:31

but the squint-cljs lib contains compiled CLJS code

Andrea12:01:35

also, why is babel transform pass kicking in, also for the :esm target? What is the transformation doing?

borkdude12:01:59

@U05224H0W That is true, but squint-cljs/core.js is pure es6

thheller13:01:50

well the error is pretty clear. it uses code the closure compiler doesn't support

thheller13:01:00

so there is nothing to do, except NOT having it process this code

thheller13:01:11

which you do via :js-provider :import for :esm builds

Andrea13:01:43

ah ok, @U04V15CAJ I see you do that as well here: https://github.com/squint-cljs/squint/blob/c50c4c2582aeda9e874a867e19a2bfcfc9e4caab/shadow-cljs.edn#L4-L5 how would I make squint core functions available to the browser? According to: https://shadow-cljs.github.io/docs/UsersGuide.html#_third_party_tool_integration I need some extra tool to process shadow output

borkdude13:01:14

@U9EQP1K0X You could use another bundler on the final output, e.g. esbuild or so

borkdude13:01:34

npx esbuild public/main.js --bundle --minify --platform=browser --outfile=public/main2.js --format=esm

borkdude13:01:39

something like this

borkdude13:01:06

or for dev builds, include squint-cljs core.js yourself in the HTML

borkdude13:01:30

Here is a playground which also does that: https://squint-cljs.github.io/squint/

borkdude13:01:56

<script async src=""></script>
    <script type="importmap">
      {
        "imports": {
          "squint-cljs": "",
          "squint-cljs/core.js": "",
          "squint-cljs/string.js": ""
        }
      }
    </script>

Andrea13:01:40

cool thanks, now I’m using shadow to compile other NPM dependencies together with real cljs sources in the same project, how can I make :js-provider selective to just squint-cljs/core? Is that :resolve https://shadow-cljs.github.io/docs/UsersGuide.html#js-resolve?

borkdude13:01:57

If I remember correctly, you can also use:

:js-options {:keep-as-import #{"fs"}}

borkdude13:01:08

(replace fs with squint-cljs/core.js)

borkdude13:01:52

or perhaps this is deprecated @U05224H0W? I don't see this option mentioned in the README

thheller13:01:51

still exists yeah

Andrea13:01:15

ehm, with

:keep-as-import #{"squint-cljs/core.js"}
in :js-options I still get the transpile error

thheller13:01:21

are you importing that file specifically?

thheller13:01:39

it is really difficult to make any kind of suggestions without seeing any code

thheller13:01:01

:keep-as-import #{"squint-cljs"}

thheller13:01:24

or whatever you are requiring in your code

borkdude13:01:24

@U9EQP1K0X Perhaps you can make a tiny repro repository

thheller13:01:29

like the exact name

Andrea13:01:34

yeah, I think I can go a bit further, and produce a repro repo if I am still stuck. Thanks a lot @U05224H0W @U04V15CAJ !

borkdude16:01:01

@U05224H0W Is there a way to run a tool like webpack or esbuild after shadow is done compiling in watch mode, to resolve the "keep-as-import" imports? Because the browser still needs to have those files. We could use import-maps for those and then serve those files manually, but that's also a bit tedious

thheller16:01:41

no, that is not supported

borkdude19:01:02

@U9EQP1K0X figured it out by calling esbuild in a build hook

martinklepsch16:01:32

Is there a way to insert a “preamble” of sorts into node REPL sessions? I find it quite interruptive to have the node-repl die just because of an unhandledRejection and usually run a snippet like the one below to avoid this. Is there a way to configure this at a project level?

(js/process.on "unhandledRejection"
                 (fn [err]
                   (js/console.log "unhandledRejection" err)
                   (tap> {:unhandledRejection err})))

thheller16:01:22

if its a build repl you can just put it into a ns an :preloads it?

martinklepsch17:01:50

Ah yes, that works perfectly. I somehow assumed preloads wouldn’t be a thing with node but I’m realizing I didn’t think about that very much otherwise I would have realized they probably work just the same 🙂

martinklepsch17:01:36

I find this unhandledRejection stuff sufficiently annoying that I’d love for it to be part of the shadow node repl by default somehow. I think it might also be quite confusing for newcomers because some REPL clients don’t report it very well when the underlying node process dies.

thheller17:01:36

the trouble with this is that is can happen anywhere

thheller17:01:14

so also in REPL internals, which may end up causing a infinite exception loop and burn your CPU to death 😛

😄 2
thheller17:01:24

so I'd rather not

martinklepsch17:01:45

Could the REPL catch errors of any promises that are coming through? (i.e. more explicit)

thheller17:01:19

not sure. having looked at many node internals for many years

thheller17:01:33

there might be better hooks nowadays

martinklepsch18:01:37

I mean more like it looks at whatever the user’s expression returns and adds a .catch -- probably I’m thinking too simplistic here 🙂

thheller18:01:11

not sure thats a good idea

skylize15:01:03

> not sure thats a good idea Assuming the mechanics are viable and the exception is still reported, I'm not sure how this could be super-harmful. It could be on-by-default in dev mode, with a preamble to the reported error that "if this was production mode, your Node process would crash here." Using tap> seems a bit iffy though, since then the problem goes unreported if there is no tap reporter is set up. Maybe default to just print, but allow switching to tap> in the config?

martinklepsch15:01:34

yeah totally, tap> is specific to my setup