This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-03-25
Channels
- # announcements (8)
- # aws (50)
- # aws-lambda (6)
- # babashka (25)
- # beginners (119)
- # bristol-clojurians (5)
- # calva (25)
- # chlorine-clover (23)
- # cider (6)
- # cljs-dev (125)
- # clojure (63)
- # clojure-austin (1)
- # clojure-belgium (1)
- # clojure-dev (48)
- # clojure-europe (11)
- # clojure-italy (2)
- # clojure-nl (5)
- # clojure-spec (3)
- # clojure-uk (66)
- # clojurescript (14)
- # core-logic (5)
- # datomic (13)
- # emacs (10)
- # events (2)
- # fulcro (37)
- # graalvm (11)
- # hoplon (95)
- # jobs-discuss (9)
- # juxt (11)
- # kaocha (16)
- # meander (13)
- # off-topic (24)
- # pedestal (4)
- # re-frame (36)
- # reagent (10)
- # reitit (15)
- # ring-swagger (5)
- # shadow-cljs (23)
- # spacemacs (2)
- # sql (13)
- # tools-deps (32)
- # xtdb (11)
whats the point of that? requires transpiling before it can be loaded. so might as well emit es6 directly instead and transpile that. I'm pretty sure the closure devs themselves don't recommend using goog.module anymore.
@thheller they updated the Closure wiki 3 weeks ago recommending switching to goog.module
- do you have a link that says different?
I also I haven't seen any movement in the Closure Library to switch to ES6 modules, did you see something?
Steve Hicks did mention they were considering it but the plans seem quite unclear (they might do TypeScript)
new closure files ... I think that is meant for the closure library. not sure that applies to 3rd party code
but doesn't really matter if goog.module or ESM, right now that just complicates things. especially regarding hot-reload and doesn't really buy anything.
hmm yeah I replaced that loader years ago in shadow-cljs so dunno what the state of the goog loader is
but point taken, can probably drag our feet a bit longer and ES6 modules have the benefit of being loadable w/o transpilation
well real ESM you can't hot load at all since there aren't any global vars to replace
right now we have some.ns.foo = function() ...
and just "overwrite" some.ns.foo
on the next load
otherwise you have let foo = function() ...
or so in a module but you can't load the replacing code into that module scope
yeah I experimented a bit with ESM in the past but interop with the closure lib is annoying and other issues due to no shared global scope
it would be neat if CLJS compiler output could just be consumed as regular ESM by any other tool but that would currently mean getting rid of the closure-library either completely or rewriting the pieces we use to ESM
so it doesn't seem like a good target - unless you're talking about a more subtle strategy I don't understand
to keep REPL and hot-reload we just transpile it back down to one shared global scope
that's an interesting project (perhaps very related) - but the second part is the one I'm mostly concerned about now
yeah the transpile mode from closure just rewrites let foo = "thing"
based on the filename so var foo$$module$some$file = "thing"
or so
so technically thats just a regular global var we can dynamically manipulate or overwrite
though that's treading into pretty yucky territory - since it's relying on the renaming strategy
well that wouldn't be recognized by the closure-compiler when going through :advanced
goog.module
imho is bad. still not consumable by other tools and just complicates our story as well
another thing that we would have been better from the start is not adopting the "nested" namespaces in the first place
but cljs.core/assoc
could just be var ns$cljs$core = {}
for the ns and then ns$cljs$core.assoc = ...
but gets rid of a bunch of issues too since there'd be no more clashes for (ns foo.bar) (def thing "x")
and (ns foo.bar.thing)
unsurprising since the Racket people worked on it and there's not a good hot-loading narrative there
but it is the standard we have and gaining access to all other JS tools would open up many possibilities
transforming it into something usable in a dynamic setting is not so bad either so might be worth
I'm not personally interested in JS tooling and never think about - what do you have in mind that you think would be useful
@thheller instead of starting with ESM, what do you perceive as issues w/ just optionally generating ESM for those use cases?
I feel like if you really want ESM then maybe you don't care about the REPL that much anyway
so one of the issues I ran into when experimenting is with ESM you can't just assume there is a global scope
so you can't just access stuff which complicates some macros. say a macro generates code using (goog.string/something)
but the namespace using that macro didn't have a require for the goog.string
@thheller right that's true, the implicitly loaded nses thing is a problem in the wild
yeah lots of code relies on global references since the compiler doesn't really verify those and people like to cheat đ https://clojure.atlassian.net/browse/CLJS-712
@thheller isnât that goog.string
problem present in current cljs as well? best practice is to have cljs namespace doing implicit macro requires with all needed requires and document that macros must be used through that cljs namespace only (to force all requires as well), wouldnât this strategy work with ESM as well?
import maps aren't related to CLJS in any way. just make ESM more bearable, otherwise it is too strict and probably the reason it isn't as widely adopted. eg. react still doesn't ship ESM code.
@darwin it isn't present as long as there is a global shared scope and something loaded that namespace before you accessed it
yes, but that is not always the case, e.g. when I use a macro from some library first time and it generates code which uses some namespaces I have no clue about, I only discover it at runtime that those are missing and I have to require them
ok, but cure for this via âgoing through cljs namespaceâ would work for that goog.string problem with ESM, no? that was my original curiosity
(ns foo.bar ;; cljs
(:require-macros [foo.bar])
(:require [goog.string]))
(ns foo.bar) ;; clj
(defmacro thing [& args]
`(goog.string/foo ~@args))
(ns foo.consumer
(:require [foo.bar :as bar]))
(bar/thing 1 2 3)
I still think the closure approach of namespacing everything into one shared global scope is best
but at least with ESM we can transpile to get that world when people follow the spec
considered this trickery to get back global scope with ESM? https://mathiasbynens.be/notes/globalthis https://github.com/ungap/global-this/blob/master/esm/index.js
just did a quick test with node: https://github.com/darwin/esm-trickery