Fork me on GitHub
#shadow-cljs
<
2023-03-04
>
Stuart00:03:15

Well, I now hate webpack with a hatred I wasn't sure was possible 90 mins ago

🙃 2
alexdavis21:03:46

I have a js file in my cljs project, really just out of lazyness because I want to copy some js example code and don't really know how to translate the async/await syntax. Anyway it all works fine in dev but under advanced compilation for some reason keys in objects are getting $ put around them and everything breaks. Here's an example of the js function

export function createIDBPersister(idbValidKey) {
  return {
    persistClient: async (client) => {
      set(idbValidKey, client);
    },
    restoreClient: async () => {
      return await get(idbValidKey);
    },
    removeClient: async () => {
      await del(idbValidKey);
    },
  };
}
and here is the result of console.log(createIDBPersister())
$persistClient$: async $client$$ => {…}
$removeClient$: async() => {…}
$restoreClient$: async() => {…}
[[Prototype]]: Object
It also renames my headers map for a fetch call so I start sending
$Authorization$: "Bearer ...."
which obviously breaks stuff too. the issue is only for code in this one js file which i'm importing into my cljs like
["/js/myJsFile" :refer [...]]

alexdavis21:03:04

I guess the dollar signs are just because I have pseudonames/pretty print turned on to try and debug other advanced compilation errors, when they are turned off the keys are just minified which I guess is the issue. Is there any way to tell shadow to not put a specific file into advanced compilation? I feel like it should never do that for js files anyway

alexdavis22:03:15

definitely advanced compilation issue, under :optimizations simple it works fine

thheller22:03:33

yes, :pseudo-names turns persistClient to $persistClient$ as a marker that it will be renamed, while still being able to tell what it was renamed from. purely a debugging aid, as you noticed without pseudo-names they are just shorter

thheller22:03:33

the renaming is intended, after all that is part of :advanced

thheller22:03:51

can you explain why the renaming is problem?

thheller22:03:22

if you use things properly in your code these references will also be renamed and everything will be happy

thheller22:03:48

same as they would be if you were to write it in CLJS directly

alexdavis22:03:35

I think the problem is that it seems npm libs don't get run through advanced optimisations, and this client is passed to an npm lib which uses it, and then the names don't match up

alexdavis22:03:52

At least I think that's what's going on

thheller23:03:04

yes, npm libs only do :simple.

thheller23:03:22

ok it wasn't clear that it isn't the CLJS code using the JS code, it is other npm libs

thheller23:03:27

then what you want is externs

thheller23:03:35

they prevent the renaming

thheller23:03:00

or you could include the JS code in a different way, so it also only goes through :simple

alexdavis23:03:56

oh? I think that would be my preferred approach. does that involve making it cjs compatible? or is it a shadow config option?

alexdavis23:03:14

I guess my other option is just translate it to cljs and then auto externs should do its thing?

thheller23:03:25

you create a folder that you put all the JS code in. say packages/your-js-code

thheller23:03:57

so there is a packages/your-js-code/myJsFile.js

thheller23:03:31

you then configure :js-options {:js-package-dirs ["packages" "node_modules"]} in your build config

thheller23:03:07

and from CLJS you then (:require ["your-js-code/myJsFile.js"]) like any other npm package

alexdavis23:03:54

The required JS dependency "js/myJs" is not available, it was required by "app/core.cljs".

Dependency Trace:
	app/core.cljs

Searched for npm packages in:
	/Users/.../packages
	/Users/.../node_modules
alexdavis@Alexs-MBP-2 myProject % ls packages/js
myJs.js
Maybe I'm not understanding something, do I need a package.json

alexdavis23:03:08

I don't really know how node_modules/npm works

thheller23:03:09

well first of all don't use js as the name. js/ has special meaning in CLJS, so using it like this is asking for trouble

thheller23:03:41

package.json is not required, but helps for certain things. just a npm init -y in that packages/your-lib folder is enough, doesn't need anything else

thheller23:03:23

npm works by taking the require you make and looking up a file

thheller23:03:40

(:require ["some-npm" ...]) looks for node_modules/some-npm/package.json

thheller23:03:13

(:require ["your-lib/myJs.js"]) looks for packages/your-lib/myJs.js first, then if not found node_modules/your-lib/myJs.js

thheller23:03:17

nothing more to it really

thheller23:03:07

package.json is only relevant if the file isn't mentioned directly

thheller23:03:26

"your-lib/myJs.js" is referencing the file directly, so no package.json is used

alexdavis23:03:34

ok so I am now requiring directly like (:require ["helpers/myJs.js"]) and my file is in packages/helpers/myJs.js but it still won't find it

alexdavis23:03:49

probably I am doing something silly but not seeing it...

alexdavis23:03:47

does it matter that this js file is using export function ... and other esm syntax?

thheller23:03:59

beware with the name of you package. you will effectively override the name of a package in node_modules. so, pick something that is unique enough to not interfere

thheller23:03:05

no, that does not matter

alexdavis23:03:53

definitely no collision, though even if it was overriding I would expect a different error

thheller23:03:05

I don't see why it wouldn't work. unless you are maybe on some ancient shadow-cljs version?

thheller23:03:36

make sure those are regular files, no symlinks or whatever

alexdavis23:03:46

2.19.5 in node modules and 2.21 in deps (not sure what is used for what). They are normal files

thheller23:03:27

and you just created this packages directory? it didn't exist prior with some already defined meaning?

alexdavis23:03:39

nope, just created it in the root of the project

thheller23:03:39

and you didn't do anything npm related in your main package.json?

alexdavis23:03:59

no changes other than new packages folder and updating the require

thheller23:03:01

for good measure try restarting shadow-cljs

thheller23:03:22

not sure why that would change anything but always helps to verify you are in the correct proejct and in the correct folder

thheller23:03:41

/Users/.../packages you dotted this, so you'll have to verify yourself 😛

alexdavis23:03:17

Still no luck... I am going to sleep now, in the morning I will put together a minimal example repo (and then it will probably start working and I'll notice some dumb typo 😄)

alexdavis23:03:38

Thanks for all your help though, I at least feel I understand what is going on a bit better

alexdavis10:03:20

ok well I setup the smallest example I could and still get the same problem, hopefully you can see what I'm doing wrong here https://github.com/armincerf/tmp-shadow-issue-example

thheller10:03:04

hmm I guess some change I did made the package.json mandatory. go into cd packages/myAppJsFiles; npm init -y fixes it

thheller10:03:32

export function foo() {
  return 'foo';
}

thheller10:03:44

export foo () ... alone isn't valid it seems

alexdavis10:03:19

ah awesome, npm init -y did the trick! Thanks for the help, there's no way I would have solved that alone 😅

thheller11:03:42

I'm not sure why package.json is suddenly mandatory, at least I can't remember why I made it so 😛