Is it possible to include dependency only on nodejs? Something like (:require-node)?
only via https://shadow-cljs.github.io/docs/UsersGuide.html#_conditional_reading
I am a bit confused with the missing runtime error. I have a node-test build that I ran with node, but that doesn't yield a runtime, or at least not one I could yet connect to.
Hello all! I'm working on a little prototype web app built on top of AWS Amplify, and I've hit an interesting problem when applying advanced optimisations.
Amplify generates code for you that defines the attributes of models that can be found in your GraphQL backend. In my case the generated models/index.js
file contains this:
// @ts-check
import { initSchema } from '@aws-amplify/datastore';
import { schema } from './schema';
const { Product, ListedProduct, List } = initSchema(schema);
export {
Product,
ListedProduct,
List
};
The schema file is a JavaScript file with lots of data…
export const schema = {
"models": {
"Product": {
In development I can require these models from Clojurescript with (:require ["../models/index" :as model])
, and things like model/Product
work just fine.
In production, with advanced compilation, the value of model/Product
is undefined
. In fact, all three of the models I'm playing with are undefined.
(js/console.log "Models:" #js {:List model/List
:ListedProduct model/ListedProduct
:Product model/Product})
That logs this in Firefox:
Models:
{…}
List: undefined
ListedProduct: undefined
Product: undefined
<prototype>: Object { … }
grocer.cljs:272:48
I'm fairly sure this is some dead code elimination/var renaming taking place during advance compilation.
I initially expected some property was being renamed, which is why Amplify wouldn't initialise the DataStore
it provides, but given these vars resolve to nothing…
@ashnur node-test does not support a REPL. just use node-repl
instead.
yeah closure will rename this code. you can either create externs or access the names by string
something like https://github.com/applied-science/js-interop j/get-in
or so
https://shadow-cljs.github.io/docs/UsersGuide.html#_simplified_externs
is quick too though
could maybe even generate that automatically somehow
Wouldn't model/Product
get renamed consistently though?
I'm using js-interop
in places, and I looked at adding simple externs.
no because the JS file uses "Product"
(as in a String)
So I can't do something like this:
(ns foo
(:require ["../models" :as models]))
(.subscribe DataStore models/Product)
https://developers.google.com/closure/compiler/docs/api-tutorial3#propnames
I'd need to do (.subscribe DataStore (j/get-in models :Product))
?
with the simple externs you can do models/Product
In externs/<build>.txt
I need to add something like this?
# Fix Amplify's models being undefined :)
models/Product
just Product
Awesome. I'll echo ...
into a file and mint a release build now. 👍
@thheller I love you! That did it. 💥
Thank you so much!
there is no such target as node-repl
I am even more confused now 🙂
https://shadow-cljs.github.io/docs/UsersGuide.html#node-repl
thanks, I found this, but I am not yet sure how to use it for the purpose I need the repl
that will start a repl, right? then you can develop and require your code as desired
i wish it were as simple
I need to somehow connect it to my editor, right? because "no one actually types in the repl, who would do that" I saw this on twitter. And copy pasting lots of stuff is difficult anyway
yeah most likely. CIDER can do this. what's your editor?
neovim/conjure
i think if you put the nrepl options in the shadow config it will start up with that stuff and you should be able to connect as normal
I usually have to do a ConjureConnect to the nrepl port and then ConjureShadowSelect to select the build/namespace I am connecting to. But this second part doesn't work
If I write ConjureShadowSelect it tells me that the watch for the build is not running. Which is not true, it's running, but it's a node-test build.
So, just to be clear, I don't think either tool is wrong in any way, I just don't know what I don't know that would connect it.
@ashnur I don't have a clue about the conjure parts. shadow-cljs node-repl
will launch it as will (shadow.cljs.devtools.api/node-repl)
(from CLJ)
if ConjureShadowSelect
asks for a build id that would be :node-repl
(but it needs to be started elsewhere first
But what port?
the usual nrepl port
maybe there is an option in conjure to start the node-repl directly. I don't know.
the usual is already used by the actual build of the application running
ok, I started the node repl, and tried to connect to 3334 port which seem to work, but if I try to evaluate the buffer, it just throws errors
you need to do the select thingy
otherwise you are just in a clojure REPL
right, sorry, I did do that. I selected :node-repl as you said. The evaluation certainly works, I think I have a new problem now, not related to either conjure or shadow. Thanks
You may also want to use node-repl
, not :node-repl
when selecting
I'm using an js-joda
via an npm module and my target is :browser
. Unfortunately the js-joda
code contains calls to the ES2016 feature .includes
function (on Array) instead of indexOf
which fails in IE11. I've tried all sorts of shadow-cljs config combinations wtihout any luck, e.g. :js-options {:babel-preset-config {:targets {:ie 11}}
or :compiler-options {:rewrite-polyfills true}
which I believe only writes polyfills for ES6+ anyway.
Has anybody managed to configure shadow-cljs such that an ES2016 feature is re-written or polyfilled for ES5 compatibility?
the output is supposed to be es5 assuming you didn't override :output-feature-set
but maybe it doesn't detect the .includes
properly
https://shadow-cljs.github.io/docs/UsersGuide.html#_output_language_options (for reference)
there is :compiler-options {:force-library-injection #{"polyfill-name"}}
don't know the includes name though
or just add the polyfill via external lib like https://polyfill.io/v3/
Thanks, both of you. I believe I've tried the correct :output-feature-set
and other config options already, but I'll double check. Just to confirm, I don't need the babel-preset-config
at all?
I will probably fallback to adding the polyfill manually, I was just convinced that shadow-cljs would take care of it and found that idea attractive. Anyway, let me go away and check my config again. Perhaps some of the config options I've got in there are interfering with each other. Thanks
Hmm... no, I can't get it to work. Perhaps the includes
call isn't being detected properly, as you say. For completeness, the offending lines in the third-party code are chained calls, so perhaps that makes it harder to detect https://github.com/js-joda/js-joda/blob/a1a635a7e4e506dfa7a9eedcc932571bdba9c1b2/packages/locale/src/format/cldr/CldrDateTimeTextProvider.js#L226
Anyway, I will simply include the polyfills via that :force-library-injection
config key for now. Thanks!
That worked 🙂 I also uncovered a call to Object.values
. The final shadow-cljs config was :compiler-options {:force-library-injection ["es6/array/includes" "es6/object/values"]}