I'm trying to use https://pglite.dev/docs/ from within a cljs app and get some compiler errors about dynamic imports
; ["@electric-sql/pglite" :refer [PGLite]]
; ))
; Closure compilation failed with 4 errors
; --- node_modules/@electric-sql/pglite/dist/index.cjs:4
; Dynamic import expressions cannot be transpiled.
; --- node_modules/@electric-sql/pglite/dist/index.cjs:13
; Dynamic import expressions cannot be transpiled.
; --- node_modules/@electric-sql/pglite/dist/index.cjs:13
; Dynamic import expressions cannot be transpiled.
; --- node_modules/@electric-sql/pglite/dist/index.cjs:13
; Dynamic import expressions cannot be transpiled.
;
And this is even after using :compiler-options {:output-feature-set :es2020} as mentioned in the https://shadow-cljs.github.io/docs/UsersGuide.html#_output_language_options but it's not helping (and I imagine this is because it's not about imports after all).I'll be trying to use js-provider-external as mentioned here, but if there's a simpler way I'll be glad to hear about it
https://clojurians.slack.com/archives/C6N245JGG/p1705701245163689?thread_ts=1705696515.599419&cid=C6N245JGG
unfortunately you likely wont have much luck with :external. dynamic imports make the code async, which will cause issues.
best option is like to use the CDN variant, i.e. keeping the whole thing out of the build entirely
> Dynamic import expressions cannot be transpiled.
this is the least of your worries if the package is WASM related
I've managed to use WASM for via js interop, to be seen how far I get with this
you can use :target :esm and use (:require ["
i.e. translating this import { PGlite } from " from the README
not sure what output to expect from that. Will their code be bundled with mine, or will my users still make requests to the CDN? I imagine the latter
yes, users will load the files from the CDN. things will not be bundled this way
you could just place the files on your HTTP server, if you don't want the CDN dependency
yea that's what I was planning to do
just changing :target :browser to :esm does more things I don't understand yet (will the output have a different name or do I need to load it differently?)
(:require ["esm:/npm/@electric-sql/pglite/dist/index.js" :refer (PGlite)]) if you put the file in the public/npm/@electric-sql/pglite/dist/index.js with public being your http root (just an example, paths are up to you)
yes you need to add type="module" to the script tag loading the JS
otherwise things should be ok
Ahah I think I unlocked the next part of the challenge, of course it's chunked. This will keep me busy for some more time, Thank you Thomas!
those files should all be in the npm package, you'll likely need the whole dist folder
So I made some progress and can get the library to work but I'm still messing something up with the imports. I have this at some point:
(:require
["esm:/static/pglite/index.js" :refer (PGlite)]
["@electric-sql/pglite/live" :as live]
["@electric-sql/pglite-sync" :as pglite-sync]...
And as-is it doesn't work, failing at page load with Uncaught Module not provided: module$node_modules$$electric_sql$pglite$dist$live$index_cjs
BUT it works if I load the page with this code:
(:require
["esm:/static/pglite/index.js" :refer (PGlite)]
;; ["@electric-sql/pglite/live" :as live]
;; ["@electric-sql/pglite-sync" :as pglite-sync]
It loads successfully. Then I can uncomment the two lines and re-run the ns definition with the 3 :require from the REPL and I have those two available from the correct urls [see pic]
It's as-if at page load is trying to find the live before PGlite or some other ordering issue I'm yet to get to the bottom of(even though live is under pglite I didn't find the correct incantation to load it via esm:/ - and even then I have to see how to do it for pglite-sync which I imagine depends on the rest but it's in a separate module)
well you can't bundle parts but not others
so its either all esm or nothing
you can use browser import maps to help this along
That makes sense, leaving still to figure out:
1. How do I :refer something nested? (that pglite/live)
2. How do I require that pglite-sync if that depends on pglite via npm, I imagine at some point just copying dist directories to my static path stops working
for :esm builds set :js-option {:keep-as-import #{"@electric-sql/pglite" "@electric-sql/pglite/live" ...}}, which will keep shadow from bundling them
so you basically add all the electric things
but use just a regular (:require ["@electric-sql/pglite" ...]) in your code
then setup a import map in your browser to tell the browser where to get the actual files
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap
I don't know what you are doing exactly but loading a 10mb+ sql server into a browser seems like madness to me 😛
still curious if you can actually get it to work
it's to build an app that is supposed to work offline, and sync with a remote server/other devices when online
I have a smallish prototype that saves just to idb, but works offline via service workers so if this works it'll be Cool™ but it's far form working at the moment 🙂 10Mb is not a lot if it's loaded just once and then available offline, but probably still insane 😄
I mean the alternate route is going with this https://shadow-cljs.github.io/docs/UsersGuide.html#_third_party_tool_integration
and then running the output through webpack or so after shadow-cljs is done with it
basically that puts webpack in charge of the npm stuff and shadow just does the CLJS parts
https://shadow-cljs.github.io/docs/UsersGuide.html#target-npm-module also works in the same way, just not using ESM. which may make things easier or harder. depends on the constellation of npm packages really 😛
import maps should work too though
really all depends on the npm packages. I don't know how they are setup
I've only ended up here because of the dynamic import I guess, so not sure where those stand with this
there's also wasm component (that so far gave no issues)
yeah because you didn't get to that part yet 😉
I think I did manage to get pg run in wasm, because I got some writes replicated, but I might be fooling myself
well shadow doesn't support any WASM bundling whatsoever, so if you manually tweak things long enough it might work. but definitely not out of the box 😛
import map started to work and unlock new problems one at the time.
Now I'm trying to load some mjs file and get Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/octet-stream". Strict MIME type checking is enforced for module scripts per HTML spec.
So I believe the :dev-http server is not using the right content type to serve this.
I guess luckily there's a index.legacy-esm.js in that path and that allows progress, so will use that for the the time being, but otherwise I guess I can't set a middleware for :dev-http and the only solution would have been to use a reverse proxy
I fixed that 2 years ago? which shadow version are you on? 😛
https://github.com/thheller/shadow-undertow/commit/bf84dab4989f21601c52449a36fda4dabe2e067a
=== shadow-cljs version (via clojure/deps.edn) shadow-cljs version: 2.25.4 guilty! 😄