This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-03-23
Channels
- # announcements (2)
- # babashka (25)
- # beginners (33)
- # biff (13)
- # calva (13)
- # clerk (82)
- # clj-commons (3)
- # clj-kondo (8)
- # clj-on-windows (23)
- # cljdoc (6)
- # clojure (16)
- # clojure-belgium (1)
- # clojure-dev (58)
- # clojure-europe (53)
- # clojure-nl (1)
- # clojure-norway (15)
- # clojure-uk (2)
- # clojurescript (17)
- # core-async (5)
- # cursive (6)
- # datahike (1)
- # datomic (8)
- # emacs (25)
- # etaoin (21)
- # events (4)
- # graalvm (33)
- # honeysql (7)
- # hyperfiddle (1)
- # lsp (49)
- # luminus (4)
- # malli (18)
- # off-topic (63)
- # reagent (11)
- # releases (1)
- # shadow-cljs (200)
- # timbre (1)
- # tools-build (17)
Hello fellas, do you know any document or guide to host front-end and back-end in one project with shadow-cljs? I was thinking to use Macchiato for back-end. Actually, I’ve been trying out some templates and POCs but, no luck, they all fails. Any suggestions?
what question do you have? you do the frontend as usual, you do the backend as usual. really nothing changes. you just don't use the shadow-cljs :dev-http
to serve your .js
files, you use your backend. thats it.
I believe District0x on GitHub has several projects that are pure CLJS on both front and backend. But they mix deps.edn with shadow-cljs IIRC
Hi, I maintain a library that has a JS dependency. The dependency is inlined in my source code like this: https://github.com/cjohansen/dumdom/blob/master/src/deps.cljs This seems to not work for shadow-cljs users. Is there some way to make this work with shadow while still working as it does today with figwheel/cljs-build?
in general, shadow-cljs works against CLJSJS and manually injecting dependencies this way — the best chance of getting support on shadow-cljs is to declare an npm dependency and fall back to CLJSJS for figwheel users
while there are ways to get stuff like CLJSJS libraries into shadow-cljs, it is usually not recommended for several reasons: • you have full access to npm already • npm libs go through simple optimizations • externs inference eliminates the need for handwritten externs almost all of the time using npm dependencies via cljsjs is usually a “last resort” and involves shimming the namespaces from the shadow-cljs side
@U9MKYDN4Q Is there a way to use NPM dependencies with figwheel besides your current route? I would expect that is the “path of least resistence” here.
repalce this line https://github.com/cjohansen/dumdom/blob/47ae38edba82a4e86164d3d7cd62780b2decbd2e/src/snabbdom/snabbdom.js#L3
in the CLJS code you then just (:require [dumdom.snabbdom :as snab])
and snab/array
etc
well, depends. if you were defensive in your CLJS code and use goog.object
to access stuff maybe
optional but lets you access dumdom.snabbdom
in the browser console during dev. might be useful
once I moved the file to match the namespace provided to goog it works perfectly with figwheel 👍
I’ll do that before pushing it. Gotta pop in a meeting, but will let you know how it works later 👍
in case it doesn't work just adding :npm-deps {"snabbdom" "the-version"}
to the deps.cljs
should be enough to make it work with shadow-cljs
@thheller Finally got around to trying a advanced build with this solution. Unfortunately, cljs-build doesn’t seem to understand the module No such namespace: dumdom.snabbdom
hmm yeah that should definitely work. or are you maybe on an ultra ancient cljs version with cljsbuild?
That was it. Got the build going, but ran into this runtime: TypeError: t.getAttribute is not a function
. There are only two calls to this function - can I extern my way out of this @thheller or am I better off with reverting to deps.edn with the npm-deps?
I don't know. need more context for the error. getAttribute
is not getting renamed there, so likely a different issue
I guess. But just to try: how would I use the old externs with the goog module? The externs goes var snabbdom = { ,,, }
but I’m assuming they need to target something else now?
externs are just a workarround. usually better to just figure out the cause first, even if the fix might be externs
as in it tries to look these up as strings, but they were renamed, thus t
ends up as nil
or just add the full externs. shadow-cljs via :compiler-options {:externs ["path/to/externs.js"]}
return function(t, v) {
var y;
const z = [];
for (y = 0; y < q.oh.length; ++y)
q.oh[y]();
if (void 0 === t.Gc) {
y = t.id ? "#" + t.id : "";
var A = (A = t.getAttribute("class")) ? "." + A.split(" ").join(".") : "";
t = w_(r.tagName(t).toLowerCase() + y + A, {}, [], void 0, t)
}
y_(t, v) ? l(t, v, z) : (y = t.oa,
A = r.parentNode(y),
c(v, z),
null !== A && (r.insertBefore(A, v.oa, r.nextSibling(y)),
g(A, [t], 0, 0)));
for (y = 0; y < z.length; ++y)
z[y].data.me.insert(z[y]);
for (y = 0; y < q.post.length; ++y)
q.post[y]();
return v
}
I suspect the pseudo names gave me another issue, trying another compile without it
might be safer to just go with npm-deps then, sometimes these libs just don't survive :advanced
Failed to set a named property on 'DOMStringMap': 'data-$dumdom-id$' is not a valid attribute name.
Awesome, thank you so much! I will try to run it with shadow later today, but hopefully this works now.
this is guaranteed to break. I very strongly recommend NOT using goog.module
then, or finding where this is coming from and changing the code
@thheller you were right, of course - this didn’t work 😅 I’m now trying to find a way to make this work in both figwheel and shadow and both simple and advanced optimizations… The previous inline JS source as a foreign-lib works with figwheel. I’m looking at this https://shadow-cljs.github.io/docs/UsersGuide.html#publish-deps-cljs but it is unclear how I would go about using the library after doing this? js/snabbdom
?
I’m starting to think my time would be better spent just writing the damn thing in ClojureScript 😂
This is probably a non-sense question, but is it possible to have a root module that does not depend on cljs.core? My use case is to have a small module that attempts authentication. As part of the authentication process, the user is redirected to an external identity provider, and I want to avoid having to make the user download some 400 kb bundle twice. The authentication code is very small and makes up a tiny fraction of this bundle, so loading that twice is not a big deal to me. I want to lazily load the app when authentication is successful
Sweet. Is it okay to use dynamic ES import to load the app module, or should I look into using closure-library’s ModuleLoader?
@thheller A couple of months ago I was trying to get automerge 2 working with shadow-cljs, via webpack (as an external js provider), but I was never able to actually correctly import anything. I've created a minimal project that just attempts to do this - would you be willing to take a look?
slack or <mailto:[email protected]|[email protected]>
You'll have to do an npm install in that directory (I removed the node modules to make it smaller), and if you look at the "run" script, you can see what I was trying to do to package it up for webpack and shadow-cljs.
(ns minimal.core
(:require
;; automerge docs do:
;; import * as Automerge from '@automerge/automerge'
["@automerge/automerge" :as am]
[shadow.cljs.modern :refer (js-await)]))
(defn init
[]
(js-await [^js mod am]
(js/console.log "init result" (.init mod))
(println "Initialized!")))
I don't have a clue how you use any of this, but with the js-await
you get what you'd otherwise get. whether that makes it work or not I cannot tell
I think that will give me enough to go a bit further and see if maybe this stuff will work .. so thank you so much for your time and help !
I think this may explain where the promise is coming from: https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/instantiate#second_overload_example
Ah, interesting. That's there because they (the automerge people) said it was required. But interestingly, none of their js code does anything with promises to refer to that import.
I will follow up with those guys next and see if they have anything interesting to say about it ...
@thheller If I were going to use js-await
like you showed me, do I have to do that in every function that accesses the import ? I think so ?
The webpack docs say that for their async modules:
> Importing them via import
is automatically handled and no additional syntax is needed and difference is hardly notice-able.
> Importing them via require()
will return a Promise that resolves to the exports.
@thheller When you say after the first time, you only access the await'd result ... do you mean that once you access it, you store a reference the module or whatever (in an atom or something) ?
I mean that when (:require ["async-thing" :as x])
accessing the x
directly will ALWAYS return a promise. Always, no matter where or when. So, yes you await that somewhere once, preferably in the init
, then store the reference and use that instead. could be a simple (def automerge-actual nil)
and then in the await body (set! automerge-actual the-result)
. then anywhere you want to access automerge stuff you use automerge-actual
. probably create some helper functions to do so
Ok, thanks for the explanation - that is what I suspected you meant, but I just wanted to be sure. Thank you !
@thheller In the old library, which we could just require and refer to as am
, I had some references to data types (which I used with extend-type
) that I could just refer to like am/Text
... with this promise-based thing, when I have the result of the js-await
, how do I do the equivalent of am/Text
? (.- the-result Text)
or something ?
@thheller I have one more question. With this external js-provider, when I use the project nextjournal-markdown
, I get an error from shadow-cljs upon loading the page:
Any idea how one might debug this ? It happens consistently with this specific project.
this is not an error from a build using :js-provider :external
. it does not call shadow.js.jsRequire
ever at all
I mean obviously you know what you are talking about, but the markdown project works fine with normal shadow-cljs ... this error only appears when you do this webpack packaging step.
from what you posted I can tell you that the CLJS output you are loading is not from a build using :js-provider :external
I can blow away all caches but this happens in multiple projects that I've tried this in, including a brand new minimal project for the repro case. Let me try again before sending it to you, after blowing away all subdirs etc.
then it should be fine. might still be bad service workers, bad browser extensions, etc
note that the files you are sending have a lot of ._
files. don't know what this is about but they are useless 😛
Assuming that the error you are seeing is the complaint about plugin.apply not being a function, there is some discussion of similar issues elsewhere in their library here: https://github.com/valeriangalliat/markdown-it-anchor/issues/55 but I think it probably means that for now, it's best for me to find another library. I definitely don't know enough about js or js packaging to make sense of this stuff.
I'm getting "http2 is not available" trying to use amplify / AWS SDK. I see this was a bug in shadow previously, but it's still not working for me now. I tried setting the resolve to false in :js-options
but that causes the build to fail with the cause of missing a different dependency.
when/where do you get that? false just disables it, if its actually required and accessed that will cause problems
When I require "@aws-amplify/ui-react"
Build error, yeah.
Build failure: the required JS dependency "http2" is not available, it was required by "node_modules/@aws-sdk/node-http-handler/dist/cjs/node-http2-handler.js". Dependency Trace:
aoda/amplify/app.cljs
aoda/amplify/views.cljs
node_modules/@aws-amplify/ui-react/dist/index.js
node_modules/aws-amplify/lib/index.js
node_modules/@aws-amplify/core/lib/index.js
node_modules/@aws-amplify/core/lib/Providers/index.js
node_modules/@aws-amplify/core/lib/Providers/AWSCloudWatchProvider.js
node_modules/@aws-sdk/client-cloudwatch-logs/dist/cjs/index.js
node_modules/@aws-sdk/client-cloudwatch-logs/dist/cjs/CloudWatchLogsClient.js
node_modules/@aws-sdk/client-cloudwatch-logs/dist/cjs/runtimeConfig.js
node_modules/@aws-sdk/node-http-handler/dist/cjs/index.js
node_modules/@aws-sdk/node-http-handler/dist/cjs/node-http2-handler.js
Searched for npm packages in:
/home/bhlieberman/dev/clj/cljs/amplify-ui-demo/node_modules
browser
did you try using webpack as described here https://code.thheller.com/blog/shadow-cljs/2020/05/08/how-about-webpack-now.html#option-2-js-provider-external ?
no, but I'll give that a go
that worked @thheller thanks a bunch. I did want to note something (I think is) strange. The output of webpack created a directory named libs.js
, and I had to reference the main.js
inside that directory to get the build to run.