Fork me on GitHub
#clojurescript
<
2020-09-24
>
neilyio15:09:05

I need my generated Javascript to have a module.exports = my_cljs_func, I'm not really sure where to start with this. I'm using Boot right now, but it seems like this is either somehow done with ^:export metadata or https://clojurescript.org/reference/compiler-options#target-fn. Any thoughts?

Lone Ranger17:09:46

you mean on advanced compilation?

neilyio17:09:56

I'd like to know if it's possible on none, simple, or advanced. I'm trying to use ClojureScript with Next.js for static site generation, and Next.js requires one .js file for each generated html web page. Each .js file needs to export its render function with module.exports = my_render_func.

Lone Ranger20:09:33

😬 ah that could be tough

neilyio20:09:52

Tell me about it I can't find an answer anywhere haha

Lone Ranger20:09:57

it's the "each js" file that would be the tougher part, I think

Lone Ranger20:09:24

Because you'd have to do something like code-splitting to get that to work in a single project

neilyio20:09:03

Yep. I was hoping there'd be a compiler option to just "mirror" my source directory of .cljs files with the output .js files.

neilyio20:09:02

@thheller had a clever idea that will save me in the meantime: you could just create a `foo.js` yourself that just has `module.exports = require("./path-to-npm-module-output/your.ns").the_export;` with `(defn ^:export the-export [foo bar] ...)` in that ns

Lone Ranger20:09:56

mmm that would be a very good approach. Probably easier than what I was going to suggest

neilyio20:09:22

Would still love to hear your idea. I'm always happy to complicate these things.

Lone Ranger20:09:39

It's an easy way to build two different files. I imagine it would be fairly easy to produce multiple js files this way in advanced compilation. Note that I would ABSOLUTELY use the prefix option to prevent namespace collisions

Lone Ranger20:09:19

Then in the files themselves you could do something like (js* "module.exports = blah") at the bottom

Lone Ranger20:09:40

I'm not saying it's better. But it IS complicated!

Lone Ranger20:09:28

Another option is... you could use a combination of :closure-defines with a case statement at the bottom of the page

Lone Ranger20:09:56

(case goog/PAGE
  "main" (js* "module.exports = main_render)
  "blah" (js* "module.exports = blah_render))
where goog/PAGE is defined with
:closure-defines {PAGE "main"}
for instance

Lone Ranger20:09:13

hmm maybe not complicated enough

Lone Ranger20:09:22

I'll keep thinking about it :rolling_on_the_floor_laughing:

neilyio20:09:44

That's a wild approach. I'll have to try it out, thanks for walking me through it!

thheller21:09:24

@U3BALC2HH your approach to workers is not ideal. both builds will duplicate a lot of code and none of it is shared. if you use :modules to split the code you can share code which means the user only has to download a large portion once and the page/worker can share it

💯 3
3
thheller21:09:06

you can of course do it but something to be aware of

Lone Ranger22:09:05

Absolutely... my only claim was that it was minimally viable and overly complex 🤪

Lone Ranger22:09:48

I love the module idea!

Lone Ranger20:09:12

Oh man, you're talking to the right cat avatar internet guy, then

John Christopher Jones22:09:22

@neil.hansen.31 Sounds like a good idea to start with. I did find that this is https://shadow-cljs.github.io/docs/UsersGuide.html#target-node-library. You could probably automate rewriting a build target section of your shadow-cljs.edn based on the contents of your pages namespace. 🙂