This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-24
Channels
- # adventofcode (2)
- # anglican (1)
- # announcements (4)
- # aws (2)
- # babashka (28)
- # beginners (18)
- # brompton (3)
- # calva (22)
- # clj-kondo (2)
- # cljdoc (29)
- # clojure (41)
- # clojure-europe (28)
- # clojure-gamedev (14)
- # clojure-nl (2)
- # clojure-spec (2)
- # clojure-sweden (1)
- # clojure-uk (6)
- # clojurescript (53)
- # css (3)
- # cursive (6)
- # duct (3)
- # emacs (5)
- # fulcro (29)
- # introduce-yourself (1)
- # liberator (5)
- # lsp (1)
- # malli (11)
- # meander (4)
- # nbb (11)
- # off-topic (17)
- # pathom (2)
- # polylith (8)
- # practicalli (1)
- # react (6)
- # reagent (11)
- # releases (2)
- # rewrite-clj (11)
- # shadow-cljs (59)
- # tools-deps (21)
- # vim (11)
I'm making a scripting tool for node, but I'm in a bit of a CommonJS / ESM style conflict.
So for example path
is required as (:require ["path" :as path])
, this is the default style which only works with CommonJS.
Some libraries now only expose ESM in their newest version. E.g. term-size
must be required using (:require ["term-size$default" :as term-size])
because it's exposed as an EcmaScript module. But it's probably not good to mix CommonJS and EcmaScript in one namespace form, is it? My tool can support it, but it's just a matter of: is it a bad idea? If styles cannot be mixed, then (:require ["path" :as path])
has to become (:require ["path$default" :as path])
which is more verbose.
So the question is: do I go with the more verbose $default
style of import, so all ESM libs can also be required in the same style, or should I consider some other solution?
What happens when you write a "normal" CLJS library for node which requires (:require ["path" :as path])
and then require that library in a project which is a compiled as an ESM module?
compiling CLJS to an ESM module is already in pretty unpaved territory. i'm not sure what would happen; probably would depend on the build tool
maybe stupid question: how do you handle aliasing with ESM that don't have a default export?
@borkdude this was the reason for leaning on Webpack or any Webpack-like bundler - to punt this problem to where it belongs
as far as I can tell all import patterns are supported by ClojureScript because it's not our problem
since built in modules export both a default object and named exports, if you handle aliasing with non-default exports then you might not need to change anything for importing built ins, which I think would be the biggest worry
@lilactown Currently (:require ["foo" :as foo])
is implemented using require()
, but this brings the limitation that I'm currently trying to address: you can't load ESM modules using that
@dnolen this is a custom tool that doesn't use the normal CLJS tooling. it's a one-off scripting tool that interprets the ns form on its own and then uses dynamic require or dynamic import (the latter is needed for ESM)
@borkdude but that's what I'm saying - are you going to let people load arbitrary modules from NPM?
actually I tried (:require ["path" :as path])
using dynamic import and it just works as before, while path
is an object with a default object inside of it. Hmm, perhaps there isn't a problem at all then.
@dnolen yes, arbitrary modules, but those modules are installed via npm install foobar
. my tool loads them from the script directory at runtime, no bundling
anything else means users cannot use whatever they - want following the existing documentation
@borkdude I'm telling you - if you don't use a bundler then you do not let people arbitrary modules
that doesn't make sense to me. if borkdude's loading these libs into Node.js, he needs to ensure his code calls the library correctly - but otherwise Node.js shouldn't require a bundler AFAICT
I don't know why I need a bundler, sorry. Perhaps I'm just misunderstanding what this is. This currently works with the tool.
$ npm install csv-parse
$ npm install shelljs
(ns script
(:require ["csv-parse/lib/sync" :as csv-parse]
["fs" :as fs]
["shelljs" :as sh]))
(println (count (str (fs/readFileSync "script.cljs"))))
(prn (sh/ls "."))
(prn (csv-parse "foo,bar"))
this repo has a bunch of opinions about using CJS + ESM on Node.js: https://github.com/johnloy/esm-commonjs-interop-manual#no_entry_sign-dont-run-a-cjs-application-in-node-with-esm-dependencies
so when switching the resolve+loading of npm libs to all ESM-style, then ["shelljs" :as sh]
becomes ["shelljs$default" :as sh]
in the scripts, that's the issue I'm trying to address here: it would perhaps be annoying if users had to write $default
a lot, but perhaps it's for the better to make it more predicable what's happening, without introducing magic
For the value that nbb gives I think it's entirely acceptable to ask consumers to type out a few extra characters 🙂
yeah I think it's best to pick one module resolution pattern. that seems like a "learn once, works forever" w.r.t. using ESM with nbb
I'm not sure, it might depend on how shelljs
gets bundled with your ClojureScript, since it's a CJS module
while I think shadow-cljs is a fine tool - it's one of the thing I like about the least - that it's bifurcating people understanding of requires - I understand that it needed to solve a problem we didn't solve first - but it's muddied the waters for sure
now that there's a standard pattern - just support the standard pattern as the main thing
there's some essential complexity here that isn't just shadow-cljs muddying the waters
knowing how your deps will be imported in your CLJS code (not talking about borkdudes tool atm) requires understanding your bundler and how CLJS will interact with it
the question that borkdude was raising was about how to handle CJS dependencies if he goes all in on emitting ESM code for his scripts
Node.js is going to be in mixed-mode for awhile AFAICT, due to the differences between CJS and ESM. but the community does seem to be slowly migrating
but aren't years in the JS community like decades in real life?