Hello. I'm trying to require js in the same project, compiled from typescript, following this guide: https://shadow-cljs.github.io/docs/UsersGuide.html#_requiring_js, but I can't seem to get it to work.
I have a state.ts file that's compiled to out/state.js
- I added out
to the shadow-cljs source-paths
, since I read that js requires are read from the classpath, then I tried to require it in the ns form like (:require ["out/state" :as state] ...
but it just appears to be an empty object :thinking_face:. This js file has exports and is used elsewhere in typescript files in the project.
It does build though via shadow and I don't get any errors - if I rename state in the path to something like statee
that doesn't exist I see this error printed: JS reload failed Error: Cannot find module 'out/statee'
so it appears that it at least sees the module state
since I don't get an error with that.
Ok now seeing the error: Cannot find module 'out/state'
so maybe it's not found. Hoping/guessing I'm just missing some small detail about this process.
> node ./main.js
file:///home/john/cdktfclj/main.js:5
var SHADOW_IMPORT_PATH = __dirname + '/.shadow-cljs/builds/cdktf/dev/out/cljs-runtime';
^
ReferenceError: __dirname is not defined
at file:///home/john/cdktfclj/main.js:5:26
at file:///home/john/cdktfclj/main.js:1789:3
at ModuleJob.run (internal/modules/esm/module_job.js:152:23)
at async Loader.import (internal/modules/esm/loader.js:166:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5)
I'm getting this error with the code that comes out of shadow-cljs compile app
AMD/CommonJS is pretty much the same so that doesn't matter
and no this is not configurable. there is an experimental :target :esm
but you shouldn't use this when building for node currently
I didn't think CommonJS
did an IIFE like AMD
did
it doesn't have to but it makes no difference. it is not the cause of your issue and would not affect anything. __dirname
not being present is purely an effect of node loading the file as a ESM module
you're right -- the __dirname
problem went away when I removed the --experimental
flag to node
"type": "module"
is the same as --experimental
why do you have that in the first place?
because I need to interop with typescript and when I generate it as CommonJS
instead of ES2015
then I get the error at the top of the other thread: module$docker$index is not defined
if you make a reproducible example I can take a look but so far I'm just guessing
sure, I can do that
looks to be related to "type": "module",
inside my package.json
hmm ... it looks kinda like shadow-cljs
is maybe outputting AMD
instead of CommonJS
-- is this configurable?
@brandon.ringe I tried to explain this in the guide but I will try again. the PATH you require MUST be on the classpath and MUST be an actual path. ["out/state" ...]
will look for node_modules/out
since it doesn't start with /
or ./
. so instead use ["/state.js" :as state]
. the classpath will then be searched in order and if you have out
on the classpath it'll eventually find <project>/out/state.js
Hi there @thheller. Sorry for pinging you directly but I feel this is something only you can fix. So I'm working on a fulcro project with Elastic UI and stumbled across this error Uncaught (in promise) Module not provided: ./assets/plus.js
when trying to use a React component from the UI library. But this component works perfectly find in a normal JS library, in fact I was testing around with CodePen and there's nothing wrong with it. So I suspect it has something to do with shadow-cljs. I've created a GH issue with more details here: https://github.com/thheller/shadow-cljs/issues/840. Thanks in advance 🙂
answered on github
@thheller Are the goog.provide lines generated by shadow or by cljs compiler?
And is there a reason that it’s important that throw new Error('Namespace "' + name + '" already declared.');
be thrown from within goog.provide
declaration? I’m trying to get webpack to happily hot reload cljs generated with :npm-module
@mail024 why do you want to let webpack do that instead of shadow-cljs?
I’m experimenting with cljs/nextjs interop
So I want the repl connection, but to leave everything else up to the rest of the toolchain.
module loading; optimisation; HMR; etc
been a while since I looked at webpack HMR but it used to have issues with reloading cljs code
the exception you can get rid of by deplacing goog.provide
with goog.constructNamespace_
as done here https://github.com/thheller/shadow-cljs/blob/f28003cbb062fd27685048e8b4793eb05ca8f829/src/main/shadow/cljs/devtools/client/env.cljs#L145
if you are experimenting with interop stuff you should really use :target :esm
instead
thanks! I actually just made a patch goog that does just that. Yours is simpler though
:npm-module
has all sorts of little quirks that'll really get in your way
ok thanks. I’ll check that out
Been running through the clojurescript codebase to try get a better idea of how everything works. My experience with cljs thus far has largely been via shadow-cljs so I’m not that familiar with standard cljs emmission.
https://clojureverse.org/t/clojurescript-compiler-internals-with-mike-fikes/7141 might help
Thanks!
I guess you saw https://github.com/thheller/next-cljs ?
yeah, I worked through that a few months back. Ultimately I decided to write something native clojurescript. But I’m experimenting again with interop. Want to try see if I can get a clean interop story with native js tooling
Do you know if the emmitter is the only place that cares about google closure? Does it feed in higher up?
what do you mean by "cares about google closure"?
If I were to swap out the cljs emmitter and replace it with something that doesn’t output in a google closure friendly way, how much would I need to change up in the analyser say
about everything
got you
I have been thinking about writing a cljs compiler variant that emits pure modern ESM code with no traces of closure
because I think this really cannot be retrofitted into the current compiler
but yeah its a massive amount of work
Would love to talk to you about this. It’s something I want to see and would be prepared to support. financially or otherwise
it might be possible but I'm already working around too many issues with shadow-cljs that this is not an avenue I wanted to pursue
its mostly a time issue for me. the final "gain" is questionable since things like the REPL and hot-reload will get much harder
the only downside of the current way really is that JS tools don't like it but otherwise its pretty nice
I mean you can always do the hacks that :target :esm
or :npm-module
do and that works ok enough for a bit
but to do it cleanly things need to be really different
I think the downside of JS not liking it actually is everything for me
I’ll DM you
yeah getting smoother JS interop would be useful for a lot of tools
Thanks for explaining more. I've managed to get to a new error with that. I have out
on the classpath (have verified with shadow-cljs classpath
), and state.js
exists in out
, along with other js files and directories containing js files. When I try to require the file with ["/state.js" :as state]
I get the following error:
[:calva-lib] Build failure:
FileNotFoundException: /home/brandon/development/calva/out/doc-mirror (Is a directory)
java.io.FileInputStream.open0 (FileInputStream.java:-2)
java.io.FileInputStream.open (FileInputStream.java:195)
java.io.FileInputStream.<init> (FileInputStream.java:138)
shadow.build.data/sha1-file (data.clj:341)
...
It's true that doc-mirror
is a directory, but I don't see how that is relevant / why it matters :thinking_face:
That directory does contain an index.js
file (along with others), but it's the first one to contain one, alphabetically. Not sure if that has anything to do with the error.
then use /doc-mirror/index.js
. it doesn't do any of the npm nonsense of guessing which file you mean. just refer to the file by name.
Sorry if I wasn't clear. I don't want to import that file. I want to import /state.js
which is in the out
directory. out
is on the classpath, the file is in out
and I import it at "/state.js" :as state
. So I'm referring to it by name and starting with /
so it doesn't check node_modules. When I try to do that, I get that error about that unrelated directory.
I can make an issue with a repro case if you think that would help.