Fork me on GitHub
#shadow-cljs
<
2021-12-22
>
thheller06:12:41

@jhacks :asset-path controls that. you can set it to a full domain. there is also :compiler-options {:source-map-inline true}, so they'll become part of the file itself with no extra request. makes the files rather huge though.

🎉 1
rberger09:12:56

I am importing some javascript ui-component code (`CardACollection.js`) that was generated from Amplify Studio (it was actually JSX code that was processed by babel into JS code) and it has this import:

import React from "react";
import { Rental } from "../models";
I set things up as per https://shadow-cljs.github.io/docs/UsersGuide.html#_javascript_dialects with this layout:
.
├── package.json
├── shadow-cljs.edn
└── src
    └── main
        └── amplify_rental_reagent_app
                                     └── core.cljs
    └── js
        ├── .babelrc
        └── ui-components
                        └── CardACollection.jsx
    └── gen
        ├── models
                 └── index.js
                 └── index.d.ts
        └── ui-components
                        └── CardACollection.js
Also have set up to use the webpack build as described in https://code.thheller.com/blog/shadow-cljs/2020/05/08/how-about-webpack-now.html#option-2-js-provider-external
:js-options {:js-provider    :external
                :external-index "target/index.js"}
The problem is that the import statement in the ui-component code is causing shadow-cljs to error out with:
[:app] Build failure:
FileNotFoundException: /Users/rberger/work/aws/amplify-rental-reagent-app/src/gen/models (Is a directory)
Is there a way to make that not happen? This JSX/JS code is all being generated by Amplify Studio and would prefer not to have to manually change that code… The repo with all this is at https://github.com/rberger/amplify-rental-reagent-app

thheller10:12:12

@rberger including classpath JS is much stricter than regular npm resolve so you'd need to rewrite import { Rental } from "../models"; to import { Rental } from "../models/index.js";

rberger22:12:30

@thheller That works (though it will be painful to do, since the JS code is auto-generated from an upstream process not under my control, but I’ll deal with that for now). But that seemed to just lead to another issue: It looks like this code which, is pulled in as JS files in the CLJS repo, needs to be part of the :js-provider :js-external mechanism. Is there a way to tell shadow-cljs to include a tree of JS code in the :externa-index in addition to the npm modules to be processed by the external webpack process? At least I think that is what would fix it. The actual issue is that import { Rental } from "../models/index.js"; has the file parsed, but Rental is not set properly. I logged when Rental is set in `models/index.js

const { Rental } = initSchema(schema);
console.log("index.js Rental: ", Rental);
export { Rental };
and after the import in CardACollection.js
import { Rental } from "../models/index.js";
console.log("Rental: ", Rental);
And I see in the console:
index.js Rental:  ƒ Model(init) {
            var instance = (0,immer__WEBPACK_IMPORTED_MODULE_1__.produce)(this, function (draft) {
                initializeInstance(init, modelDefinition, draft);
                var …
main.js:1455 ReferenceError: Rental$$module$models$index is not defined
    at eval (CardACollection.js:27)
    at eval (<anonymous>)
    at Object.goog.globalEval (main.js:488)
    at Object.env.evalLoad (main.js:1563)
    at main.js:1744

rberger23:12:47

Its also possible I’m not doing the JSX -> JS conversion right to generate this JS code. I am following the procedure in https://shadow-cljs.github.io/docs/UsersGuide.html#_javascript_dialects. Might there be more configuration I should do to the .babelrc to make this work better?

rberger23:12:06

Only the ui-components are being processed by babel. The models code is vanilla from what is pulled in with amplify pull

rberger04:12:05

I think what I need to do is actually learn how to use webpack, add another entry to have it put the models stuff into the bundle.js

thheller05:12:20

all classpath js will be processed by shadow-cljs regardless of :js-provider since no other JS tool will have access to your classpath https://shadow-cljs.github.io/docs/UsersGuide.html#classpath-js

thheller05:12:51

however if you create a custom npm package and require it like that from CLJS you can setup webpack to do whatever you need

thheller05:12:25

ie. (:require ["my-models" :as foo]) will end up emitting require("my-models") in the JS file processed by webpack

rberger05:12:47

Yeah, I’m thinking that, but don’t know off hand how to create a npm package from a couple of trees of javascript code. Was starting to look into that

thheller05:12:57

in webpack you can then configure my-models to resolve wherever you put it. eg. via alias https://webpack.js.org/configuration/resolve/#resolvealias

thheller05:12:17

you can also probably skip the jsx conversion then and let webpack do it

rberger05:12:46

Right, is there a way to do do the webpack and not create an npm package, if I just put the jsx/js code in a tree outside of the classpath?

rberger05:12:46

The webpack docs seemed to imply there was a way to use a path instead of a module

thheller06:12:54

I linked it. alias does that. basically alias: { "my-models":the-path-to-that }

thheller06:12:35

"package` basically only means directory. nothing more. it doesn't need to be published to npm or whatever

rberger06:12:55

Ok, I didn’t realize that is what you meant. Checking that and also potentially found a way to make a tree into a local npm module https://dev.to/tomiiide/import-subfolder-modules-in-javascript-like-a-boss-15f7

thheller06:12:35

yeah basically the resolve rules of "npm" (including shadow-cljs or webpack) are that anything starting with a ./ or ../ is looked up on the "filesystem" (classpath in shadow-cljs)

thheller06:12:18

any other require looks ups folders in node_modules, or gets redirect via alias

rberger07:12:06

Thanks, the resolve alias (with a few other tweaks) got it to basically work! It also means I can have the Amplify studio generated code flow in with no changes. Now I just have to figure out how to have webpack do the babel JSX->JS instead of me doing that manually with babel.

Pavel Klavík10:12:37

Is it possible to merge shadow-cljs.edn with config defined in another edn file? I would like to have some local config which can override stuff in shadow-cljs.edn which is not commited into git.

Pavel Klavík10:12:46

In particular, we have :ssl defined in shadow-cljs and I want to turn it off for testing on mobile.

thheller17:12:19

Unfortunately no. :ssl cannot be overwritten easily since it is only setup when shadow-cljs is started

Pavel Klavík20:12:49

Is it possible to override it on the start. That would not be a problem for us.

Pavel Klavík21:12:53

For instance for lein, we have project.clj shared in Git and individual profiles.clj which can be used to locally modify settings in project.clj

Pavel Klavík21:12:18

Ok, this is actually addressed in Shadow-cljs user guide: https://shadow-cljs.github.io/docs/UsersGuide.html#config-merge

Pavel Klavík21:12:30

But it just allows to override individual builds, not the entire configuration.

thheller05:12:06

as I said there is no way to do this via any command line flags or config files

thheller05:12:24

what you could do is create a custom main function and call that via lein or clj

thheller05:12:52

(shadow.cljs.devtools.server/start! the-config)

thheller05:12:15

(-> (shadow.cljs.devtools.config/load-cljs-edn) (dissoc :ssl) (shadow.cljs.devtools.server/start!))

thheller05:12:18

of course properly required and aliased but start! with no args will just load shadow-cljs.edn and call the 1-arity start!. so you could load the config yourself and modify it however you want

borkdude16:12:40

Is it possible in some build hook to correct the output of js/import.meta.url from import$.meta.url to import.meta.url?

thheller16:12:33

import.meta.url is not supported by the closure compiler so it won't work either way

borkdude16:12:21

if I correct it in the outputted JS, it does work?

thheller16:12:25

otherwise use (js* "import.meta.url") but don't tell anyone I said that 😉

thheller16:12:38

release builds don't work?

borkdude16:12:51

of course I already tried js* but that ends up as the same

thheller16:12:53

dev builds don't run through gcc so they work yes 😛

borkdude16:12:33

maybe this is a case of an X-Y problem. I would like to print the version of the package.json of my library when people call it with nbb --version. of course I could keep the version in some different file/namespace

borkdude16:12:57

but getting info from package.json might be nice

borkdude16:12:24

so I need something like __dirname but then in the ES6-style

borkdude16:12:03

but if it's not supported, I'll just keep the stuff in some namespace

borkdude16:12:17

or I could perhaps use a clojure macro to capture the info at compile time

thheller17:12:16

can you import .json files directly? I can't remember

thheller17:12:20

otherwise just (:require ["esm:../package.json" :as pkg-json]) might work?

borkdude17:12:20

I solved it with a macro. That seems the most robust solution, just do it at compile time without any doubts.

(ns nbb.macros
  (:require [clojure.data.json :as json]))

(defmacro get-in-package-json [k]
  (get (json/read-str (slurp "package.json") :key-fn keyword) k))
(ns nbb.core (:require-macros [nbb.macros :as macros]))
(defn version [] (macros/get-in-package-json :version))

JonR19:12:32

Hi all. Curious if anyone has experience using the latest @mui/material lib with shadow. I can install and import components individually but what I would like to do is use the index import for all components (`(:require ["@mui/material" :as mui])`). When I try this though I get an error: Cannot redefine property: unstable_ClassNameGenerator. This comes from the index.js where it seems to be doing some treeshaking, importing, stuff. (I say stuff cause I'm not super familar with all the different approaches to this in JS world).

David Vujic20:12:04

I would suggest to check out the reagent-mui library, a Reagent wrapper for Material UI. For me, it has simplified things a lot, when dealing with the JavaScript/React specific features: https://github.com/arttuka/reagent-material-ui

JonR20:12:25

Nice, thanks for sharing! We're using helix so I won't be able to use that directly but will check for solution ideas. Thanks again

👍 1
jhacks20:12:54

@thheller Thank you for your help! I didn’t realize :asset-path could be set to a full domain. That fixed my problem.