Fork me on GitHub

I’m messing around with three.js and the new bundle target. I can get (require '[three]) to work through figwheel + webpack, with /node_modules/three and all’s well … I have a three ns and can call (three/AmbientLight. 0x202020) etc. Where I’m hoping for a little guidance is how to reach into other stuff in the node module.


Eg. there’s a collada/dae model loader class, and I can’t quite figure out how to phrase my (require ,,,) to get at it, eg.


(The file is sitting at /projectroot/node_modules/three/examples/jsm/loaders/ColladaLoader.js … I can cat it, but … how do I tell cljs about it in a require?)


How would you require it in NodeJS?


I think your example is an ES6 import. The bundle target will generate NodeJS require from the Clojure require macro. I'm still new to all of it, so that's all I can think of. But basically it be you need to follow what NodeJS would do.


And the you can (require 'three-collada-loader)


Hm. Yep. That’d probably do it. :man-facepalming:


Weird: no references to that in the official docs.


And good thought: guess I can just experiment and watch what shows up in the npm_deps.js after cljs compile but before it goes into webpack


Ya, I wonder if you can do (require '["./example/jsm/..." :as collada-loader])


shadow-cljs supports that but the feature was rejected for CLJS so its non-standard


Oh I think I remember now the convo about this in the ClojureScript-dev channel.


So would this work in NodeJS though?


Like is this a valid NodeJS require? Or would a NodeJS package needing to require something like that need to use the ESM module and use ES6 import on it?


shadow-cljs has different rules for classpath-js. meaning that all the files you require from the classpath will be processed by it and will eventually even go through :advanced


node will never see that file, it will already be written and be like the CLJS output as far as node is concerned


but there are some issues with node so it might not always work


all fixable but not much time to work on it


nope, failure to compile with [Figwheel:WARNING] Could not Analyze: /_SLASH_example_SLASH_jsm_SLASH_loaders_SLASH_ColladaLoader.cljs is not a relative path src/frontend/rgm/browser/three.cljs … looks like it heads through clojure.core/munge someplace


hm, weird. There’s a more recent third-party packaging of that loader that takes the form var collada = require('three-loaders-collada')(THREE);. Pretty sure I’d need to use a :foreign_libs and that JS stub re-publishing trick to disentangle that.


this translates to

    ["three" :as THREE]
    ["three-loaders-collada" :as collada-init]))

(def collada (collada-init THREE))
no need for special compiler hacks, custom packages or anything of that kind


Thanks Thomas! Seems to work. I had no idea I could just call the kinda-sorta-namespace node-provided ns as a function. It confuses clj-kondo, but I can live with that.

(ns rgm.browser.three
   [reagent.core :as r]
   [three-loaders-collada :as loader-init]))

(loader-init three)

(def *loaded-scene (atom nil))
(def scene (three/Scene.))
(def loading-manager (three/LoadingManager. #(.add scene @*loaded-scene)))
(def collada-loader (three/ColladaLoader. loading-manager))

(defn load-model
  (.load collada-loader
         (fn [model]
           (reset! *loaded-scene (.scene model)))))


I still have a broader (though now academic) question: this loader does sit in the main three.js npm module. Is it strictly necessary to re-package it to its own manual, or is there a way to require/refer to it in the main npm module? (Though I guess this was enough of a problem outside of CLJS that there are 4 (!) separate third-party re-packagings on npm).


I don't know the three package. if the file is part of the actual npm package then you might be able to directly require it via (:require ["three/wherever/the/file-is.js" :as x])

❤️ 4

holy cow, that works!


clojurescript this:

(ns rgm.browser.three
   ["three/examples/jsm/loaders/ColladaLoader.js" :as loader]))
turns into :target :bundle js that (via target/…/npm_deps.js)
module.exports = {
  npmDeps: {
    "three": require('three'),
    "three/examples/jsm/loaders/ColladaLoader.js": require('three/examples/jsm/loaders/ColladaLoader.js')  }


and since ColladaLoader.js ends with export { ColladaLoader };, the loader becomes available to cljs as loader/ColladaLoader.


oh, this is great to know.


or rather, do the injection of the base THREE lib so that it can futz with enhancing its prototype. Ugh. Whyyy.


Hey 👋 , does anyone know where I can find an example of an app that uses reitit frontend and code splitting at the same time? one that I can look at on github just to see how it should/can be done. Thanks


Is there a way to set goog.DEBUG to false when using optimizations none (nodejs build)?


Can't get it working with optimizations simple, so staying with none is my best option at the moment.


@danielstockton whats the issue? :simple should really just work as it doesn't do any of the problematic optimizations.


Tried installing react/react-dom the same version as reagent with npm, clearing compiled files etc.. but couldn't get around it


uhm you said nodejs? why is that including react-dom?


It includes reagent.dom.server to render-to-string for server side rendering


And i think reagent.dom.server requires react-dom


do you use :npm-deps? ie. let the CLJS build process bundle the npm deps?


No, just using lein cljsbuild to compile the node build and lein dependencies


it doesn't. there is an extra react-dom/server.js


If you are using cljs devtools in chrome, please it let it be known here:

✔️ 36

They are planning to remove it.


I still have a broader (though now academic) question: this loader does sit in the main three.js npm module. Is it strictly necessary to re-package it to its own manual, or is there a way to require/refer to it in the main npm module? (Though I guess this was enough of a problem outside of CLJS that there are 4 (!) separate third-party re-packagings on npm).


I did try poking at this a little, but I'm curious if anyone else has experienced this issue at all? I'm using fipp's pretty printer in CLJS and in Cursive's REPL I see the below -- in the browser, I get one js/console.log line per entry. It looks like fipp is running a single println per token...


@tekacs what version of fipp are you using? do you have this problem with a repl outside of Cursive?


@bbloom 0.6.23 (the latest, I believe) and fipp.edn/pprint does the same thing in the browser REPL, without Cursive connected


where this is the line where the js/console.log is coming from... I guess print may have different (one line per call) behaviour when enable-console-print! has been run (presumably by something in my environment)?


So I'm able to work around this, given fipp's writer behaviour, by going with: (println (with-out-str (fipp.edn/pprint object-to-print))) for the time being


which isn't ideal (not sure how it handles large objects, etc.), but certainly can work


thanks so much for your work on fipp, whilst I'm here :)


i haven’t been a clojurescript user in quite a while, so i’m not sure what the expected behavior is these days, but iirc, i always used to enable-console-print!


if you can’t for some reason, feel free to file a ticket against fipp w/ details

👍 4