Fork me on GitHub
#shadow-cljs
<
2023-08-02
>
Michelle Lim16:08:55

i'm having with the following npm library:

(:require ["@onefootprint/footprint-js" :as footprint])
when i print footprint, it's just an empty js object. the library is not public so i can't link to the source, but this is what it looks like in node_modules (screenshot). i also need to do the equivalent of this: import '@onefootprint/footprint-js/dist/footprint-js.css'; which throws an error

Michelle Lim16:08:32

hmm looks like the screenshot isn't loading, i'll try attaching it again here

thheller16:08:12

shadow-cljs does not support css, therefore requiring a css file won't work. you'll need a secondary tool for that

Michelle Lim17:08:15

gotcha, thanks! how about the main library import? is that type of import not supported?

thheller17:08:59

can't see the images, slack seems to have problems

thheller17:08:59

and this is the actual file that is getting included? I see a .cjs file. what does the package.json "main" entry say

thheller17:08:09

or does it have "exports"? or "browser"?

thheller17:08:20

package.json of that package I mean

Michelle Lim17:08:38

"./dist/footprint-js.umd.js" - ah yeah sorry, screenshotted the wrong file

thheller17:08:58

yeah you definitely don't want to include that file

Michelle Lim17:08:51

it has exports:

"exports": {
    ".": {
      "require": "./dist/footprint-js.umd.js",
      "import": "./dist/footprint-js.js",
      "types": "./dist/footprint-js.d.ts"
    },
    "./dist/footprint-js.css": {
      "import": "./dist/footprint-js.css",
      "require": "./dist/footprint-js.css"
    }
  },

thheller17:08:32

ok, so in that case shadow-cljs will follow the require by default. you can change this by setting

:export-conditions ["browser" "require" "default" "module" "import"]
in the build config

thheller17:08:48

the above is the default order, so you move "import" before "require"

thheller17:08:23

then it will use the proper .js file

thheller17:08:23

it is weird that the require is pointing to a umd.js file. that seems uncommon to me, would expect the .cjs there.

thheller17:08:47

if you can change that I'd recommend that over changing :export-conditions

Michelle Lim17:08:09

does :export-conditions go in the :js-options map?

thheller17:08:44

oh, sorry. yes it does.

thheller17:08:23

oh an you need to be on 2.25.2 for any of that to matter 😛

thheller17:08:57

if you are on an older version then "exports" is not considered. only the other top level keys, so "browser" or "main" or "module"

Michelle Lim17:08:38

oh haha. it's ok, this is from a vendor we're working with so i can try asking them for a cdn instead

thheller17:08:43

which you can also change by re-ordering :entry-keys ["browser" "main" "module"], to move module to first

👀 2
thheller17:08:22

you can also just require whatever directly and bypass all this

thheller17:08:40

so (:require ["@onefootprint/footprint-js/dist/footprint-js.js" :as footprint])

thheller17:08:35

but that only works for requires that you control yourself, so if something else still requires "@onefootprint/footprint-js" then you'll still have the problem

Michelle Lim17:08:36

oh yeah i tried that first and got ExceptionInfo: package @onefootprint/footprint-js had exports, but could not resolve ./dist/footprint-js.js

thheller17:08:45

ah so you are on 2.25+

thheller17:08:19

oh right, sorry added that stuff in 2.24+

Michelle Lim17:08:52

i tried the :export-conditions and it seemed to mess with the import of a different library

thheller17:08:32

yeah that unfortunately is a global setting and will make all packages switch

thheller17:08:54

well ideally the package just removes the .umd.js file from require, that is uncommon and not something I have seen before

thheller17:08:07

or you could maybe figure out what the umd file exports

thheller17:08:13

it is most likely a global variable

thheller17:08:30

which you'd use via js/WhateverThatWas instead of the :as alias

thheller17:08:47

but umd usually means trouble in other places 😛

Michelle Lim17:08:41

this is what's in the file:

(function (exports) {
  'use strict';

  ...bunch of stuff here

  exports.FootprintInternalEvent = w;
  exports.FootprintPublicEvent = E;
  exports.default = Nt;
  exports.identifyUser = W;

  Object.defineProperty(exports, '__esModule', { value: true });

  return exports;

})({});

thheller17:08:22

uhm is there a window.Whatever = exports; or so in there?

thheller17:08:35

otherwise that file is rather useless since the return value is never used? (which is also why you are seeing an empty object when printing the variable)

Michelle Lim17:08:03

hmm not that i can see

Michelle Lim17:08:37

tysm for the insight. fortunately vendor is amenable to a cdn

thheller18:08:49

I don't recommend using cdn versions though 😉 easier to just either use the .js or .cjs files 😛

thheller18:08:03

I doubt anyone has ever used the .umd.js file if its like that 😛

Michelle Lim18:08:34

how would we use the js file? change the package.json?

thheller18:08:38

seems to be public

thheller18:08:25

and yeah the umd.js file is definitely invalid and the problem here

Michelle Lim18:08:03

oh wow you're right haha, just realized it was actually another one (footprint-react) that wasn't online

thheller18:08:16

also public, but seems to be using the same build system and has the same problem

Michelle Lim18:08:37

changing the package.json "main" and "require" totally worked

thheller18:08:55

the issue likely is that webpack and most other JS tools nowadays default to using the "module" or exports/import key

Michelle Lim18:08:12

but would be impractical to do that after every npm install

thheller18:08:14

shadow-cljs still defaults to the older default and thats why you end up with the require and umd file

👍 2
Michelle Lim18:08:08

in your opinion would it be reasonable to ask the devs to change the package.json permanently?

thheller18:08:08

in my opinion the umd file is invalid and unusable, so yes someone should look into that. also pointing the "require" key at the umd file will make the entire thing unusable in node

thheller18:08:22

which it probably is anyways, so probably not a priority

thheller18:08:46

can you tell me which other package broke when you switched :export-conditions?

Michelle Lim18:08:12

Errors encountered while trying to parse file
  /Users/elle/local/composer/composer-web/node_modules/htmlparser2/lib/esm/index.js
  {:line 48, :column 9, :message "'from' expected"}

Ben Lieberman20:08:48

is there shadow support for resolving local-only deps?

hifumi12320:08:45

what does “local-only” mean here? local m2 repository? or?

Ben Lieberman20:08:03

yeah, ~/.m2/repository

hifumi12320:08:15

hm… in that case it should suffice to provide the GAV in your :dependencies

hifumi12320:08:42

if you mean “local deps” as in deps.edn’s :local/root then you will need to manage dependencies with a deps.edn alias and set :deps in shadow-cljs.edn to the alias

Ben Lieberman20:08:10

unless I missed an option, that throws a DependencyResolutionException bc it looks on central and doesn't find anything

hifumi12320:08:43

that is interesting. can you check if the JAR file is inside your ~/.m2 ?

hifumi12320:08:56

(I have locally installed libraries before and shadow was able to find them)

Ben Lieberman20:08:19

it is, I just put it there. It's a library I'm working on, so its at ~/.m2/repository/bhlie/<my-lib>.jar

hifumi12320:08:37

that may be the issue. the format of the folder isnt like that

hifumi12320:08:45

can you try installing it with lein install or mvn install or equivalent?

hifumi12320:08:59

the structure of the local repo is something like this

.m2/
  repository/
    group/
      artifact/
        version/
          _remote.repositories
          artfiact-version.pom
          artfiact-version.jar
          ...

hifumi12320:08:08

this is automatically handled for you by leiningen, maven, et. al

hifumi12320:08:15

i do not recommend creating this folder structure by hand

Ben Lieberman20:08:29

yeah, I'm learning that as we speak 😅

Ben Lieberman20:08:04

so once I've made the jar, I should do mvn install in the project directory and that will put everything I need in ~/.m2

hifumi12320:08:33

it depends on the library you are trying to install

hifumi12320:08:45

does it use leiningen? maven? gradle? tools.build? etc.

hifumi12320:08:59

then nobody knows unless they documented how to install it 😞

hifumi12320:08:20

there is still hope though… let’s try the following

hifumi12320:08:11

remove the GAV from your :dependencies then drop the JAR file into somewhere like a resources folder… and in your shadow-cljs.edn file, add resources to your :source-paths maybe?

hifumi12320:08:19

the idea behind this approach is to try adding the JAR to your classpath manually, and avoid having to install to an m2 repo

Ben Lieberman20:08:57

oh cool yeah I was thinking of something along those lines but e.g. java -cp only I didn't know how to make that work with shadow

Ben Lieberman20:08:21

I'll give that a go

hifumi12320:08:55

worst case scenario, we can just manually install the JAR with maven by doing something like

mvn install:install-file -Dfile=your.jar -DgroupId=group -DartifactId=artifact -Dversion=version -Dpackaging=jar
but warning: I have not tested this

😱 2
Ben Lieberman21:08:41

Should I be able to require this like any other source once it's on the classpath? I expect yes but I'm evidently doing something wrong

hifumi12321:08:04

well, I was gambling on shadow-cljs adding anything on the :source-paths to the classpath… but that doesnt seem to be the case if this doesnt work

hifumi12321:08:17

let’s try the mvn install option as a last resort

Ben Lieberman21:08:27

nice, that worked!

Ben Lieberman21:08:32

thanks a bunch for your help

👍 2