This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-09-13
Channels
- # announcements (1)
- # babashka (12)
- # beginners (10)
- # biff (9)
- # calva (2)
- # cherry (21)
- # cider (14)
- # clj-commons (76)
- # clj-kondo (8)
- # clj-on-windows (34)
- # cljs-dev (5)
- # clojure (48)
- # clojure-austin (7)
- # clojure-europe (97)
- # clojure-nl (1)
- # clojure-norway (14)
- # clojure-uk (22)
- # clojurescript (137)
- # conjure (33)
- # cursive (4)
- # datalevin (1)
- # deps-new (4)
- # devcards (2)
- # duct (3)
- # events (1)
- # fulcro (12)
- # graphql (9)
- # hyperfiddle (16)
- # jobs (8)
- # kaocha (1)
- # leiningen (6)
- # lsp (39)
- # malli (38)
- # membrane (20)
- # nbb (68)
- # observability (7)
- # off-topic (49)
- # pathom (11)
- # polylith (8)
- # portal (22)
- # re-frame (6)
- # releases (1)
- # remote-jobs (2)
- # shadow-cljs (24)
- # spacemacs (2)
- # squint (6)
- # xtdb (7)
Hello. I've been trying to get the same code-base working with both NBB and Shadow-cljs, but this seems impossible (I expect I've done something stupid 😅). Shadow is configured as :target :esm
. This is the same use case as referred to some time earlier in chat, but I've written it up here: https://github.com/dmg46664/problems/tree/main/03_nbb_and_shadow_import
anyway, according to that package on npm you should import it like this:
import WebSocket, { WebSocketServer } from 'ws';
Thanks for the quick response. Yes, the server class is from ws
as you've concluded. Assuming your last response means I should :require ["ws" :as WebSocket :refer [WebSocketServer]]
then this works in Shadow but not in NBB.
import Foo from 'ws'
is (:require ["ws$default" :as Foo])
in CLJS, since Foo is the default export
I thought there needs to be an module.exports = { default: ...
in order for there to be a default export?
Same for export default ...
in ES6
yeah... but I don't see a default export in the ws
code.... ?
To me it's weird that x = await(import('ws'))
isn't the same as (:require ["ws" :as x])
in nbb, so this is something that needs to be investigated
it is the mixture of CJS and ES6 which complicates this a lot. if ws was exposed as an ES6 module, it would be the same I think
I swear this JS module stuff has done my head in 😅
So if I read your comments above correctly, I either need to do x = await(import('ws'))
or node --experimental-top-level-await
? Much obliged!
I'm also glad that I'm not completely crazy!
what I meant to say was: you can check how modules are imported by doing that manually
but it's not exactly the same in nbb as when I'm doing that, which is what I would expect... it's complicated
Coolio, thanks for confirming. Yes I was reading your JS as assumed clojure, hehe. Should I leave this with you? Do you need anything else from me?
Or are you asking me to debug it?
if nbb behaves differently than shadow-cljs + target esm then I think it could be a bug in nbb: issue welcome
no problemo, will raise! 🙂
I've assumed that NBB defaults to a context of ESM. There's no switch for it to behave differently... ?
So this is kind of a repro of what happens in nbb vs vanilla import:
import { createRequire } from 'module';
import { pathToFileURL } from 'url';
const req = createRequire(pathToFileURL('./script.cljs'))
const ws = req.resolve('ws');
const mod = await import(ws);
console.log(mod);
const mod2 = await import('ws');
console.log(mod2);
the logging of mod seems different than the logging of mod2, although they are very similar
I think it is because of this:
"exports": {
"import": "./wrapper.mjs",
"require": "./index.js"
},
nbb is going through createRequire since that allows you to resolve a module relative to a script
Written up as issue 256, just going through your comments above now.
@U04V15CAJ Well done for deducing this!
Aha, so the "exports": {
in package.json enables ws
to deliver to both CommonJS and ES6 targets. I shouldn't have looked at the code then to deduce this.
(amazing how much JS I've learned moving to CLJS...)
Amazeballs!
I guess some people may find strange corrected behaviour on upgrade... not disputing it's the right course of action.
Confirmed it works! Incredible to watch you work.
Thanks a ton. My previous post about abandoning NBB is no longer correct. I'm attempting to use polylith
to shim in different libraries for shadow and nbb and get the best of both worlds. Don't see why the majority of code shouldn't be shared. NBB has better stacktraces on load failures, and I can tweak on AWS. Shadow can use (meta ...
to show file lines on stacktraces/ ala timbre
for local testing.
I guess another difference between Shadow and NBB is the treatment of ^:export
https://clojurescript.org/reference/advanced-compilation#access-from-javascript. Shadow seems to still be able to put variables in a global scope even for`:target :esm` , at least for the watch command. For NBB this is not available. Not sure if that's what is referred to by
> In development builds however it still exports everything into the global scope via
from https://clojureverse.org/t/generating-es-modules-browser-deno/6116
I was thinking of using this for message passing between mock NPM modules in my test server, but I guess it's not proper as variables will be eradicated from global scope with ES6.
@danielmgerson nbb doesn't emit any .mjs
files so export doesn't really make sense
I have a fake @aws-sdk/xxx
module with JS code that refers back to my server code. Alas won't work with NBB. No biggy, I'll create a polylith component that wraps this differently for aws and my test server. I wish there was a way to test web-socket apiGv2 code locally within local stack. I refuse to require a live stage to test it. hehe.
I think shadow puts things in a global scope because of reloading (and ES6 reloading doesn't work, so this is shadow's workaround)
you can load nbb files from js like this:
import { loadFile } from nbb
await loadFile('src/my_stuff.cljs')
Yeah, that's not applicable to my use case. It assumes the calls only go one way.
the global var thing in shadow is only an artifact of development, I wouldn't rely on it
ooh, didn't know about that. Thanks. It's only for test harness code, not for prod code.
And by using js/globalThis
I wouldn't be relying on that shadow quirk 😄 Cheers.
@danielmgerson Ah in nbb you have to write:
(set! (.-foobar js/globalThis) 2)
js/globalThis.foobar ;;=> 2