Fork me on GitHub
#shadow-cljs
<
2023-05-16
>
alexdavis11:05:48

I'm trying to set up option #2 from this guide https://code.thheller.com/blog/shadow-cljs/2020/05/08/how-about-webpack-now.html but am getting

libs.js:57426 Uncaught ReferenceError: global is not defined
    at libs.js:57426:3
    at libs.js:57434:3
Not really sure what 'global' is supposed to refer to in https://github.com/thheller/shadow-cljs/blob/71968b1cf860d5bfb896245da61b3640542bcbdc/src/main/shadow/build/targets/external_boilerplate.js? I think global is a nodejs thing but I have :target :browser in my shadow-cljs.edn

thheller11:05:26

I never tried esbuild before

thheller11:05:37

maybe it just leaves global as is? webpack replaces it

thheller11:05:31

or are you not running this for dev? your dev build doesn't use esbuild?

alexdavis11:05:49

this is only for production builds, I'm trying to debug an issue with a library that only happens in production. Will give it a go with webpack

thheller11:05:06

do you have a comparable JS example? to me this error looks like you are supposed to pass in an arg somewhere that is missing

alexdavis11:05:49

and immediately I'm reminded of why I don't like webpack....

alexdavis@Alexs-MBP-2 ag-charts-v6-bug % npx webpack --entry target/index.js --output public/js/libs.js

Error: Cannot find module 'webpack-cli/package.json'
Require stack:
- /Users/alexdavis/.npm/_npx/89d6e678e21f2dae/node_modules/webpack/bin/webpack.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.resolve (node:internal/modules/cjs/helpers:108:19)
    at runCli (/Users/alexdavis/.npm/_npx/89d6e678e21f2dae/node_modules/webpack/bin/webpack.js:78:26)
    at /Users/alexdavis/.npm/_npx/89d6e678e21f2dae/node_modules/webpack/bin/webpack.js:178:5
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/alexdavis/.npm/_npx/89d6e678e21f2dae/node_modules/webpack/bin/webpack.js'
  ]
}
If you try the code in development it works and same for the equivalent js. I'm just mounting the charts component with the minimal number of options

thheller11:05:28

works in development could mean so many things

thheller11:05:41

development also uses the react dev version, so maybe IT doesn't like something

thheller11:05:02

need to narrow it down a little more to be sure it is actually the closure compiler/shadow-cljs messing up

alexdavis11:05:05

I've set up the same thing with plain react and made a production build and it works fine

thheller11:05:34

the error above suggests you are relying on a global install?

thheller11:05:48

npm install webpack webpack-cli in the project. remove the global if you have one

thheller11:05:18

but just glancing over some of the ag code I see a bunch of stuff the closure compiler will absolutely hate

alexdavis11:05:39

yeah I wish I didn't have to use it... unfortunately I do

thheller11:05:43

var w = "\n                function get_" + n + "() {\n                    return this." + t + ";\n                };\n                get_" + n + ";\n            ";
                        Object.defineProperty(f, n, {
                            set: eval("\n                " + (d ? "var setCount \x3d 0;" : "") + "\n                function set_" + n + "(value) {\n                    const oldValue \x3d this." + t + ";\n                    " + (h ? "value \x3d convertor(value);" : "") + "\n                    if (value !\x3d\x3d oldValue) {\n                        this." + t + " \x3d value;\n                        " + (d ? "console.log({ t: this, property: '" + n + "', oldValue, value, stack: new Error().stack });" : "") + "\n                        " + ("normal" === e ? "this.markDirty(this, " + g + ");" : "") + "\n                        " + ("transform" === e ? "this.markDirtyTransform(" + g + ");" : "") + "\n                        " + ("path" === e ? "if (!this._dirtyPath) { this._dirtyPath \x3d true; this.markDirty(this, " + g + "); }" : "") + "\n                        " + ("font" === e ? "if (!this._dirtyFont) { this._dirtyFont \x3d true; this.markDirty(this, " + g + "); }" : "") + "\n                        " + (k ? "changeCb(this);" : "") + "\n                    }\n                    " + (q ? "if (value !\x3d null \x26\x26 value._dirty \x3e " + v.NONE + ") { this.markDirty(value, value._dirty); }" : "") + "\n                };\n                set_" + n + ";\n            "),
                            get: eval(w),
                            enumerable: !0,
                            configurable: !0
                        })

thheller11:05:48

why the fuck is there eval code?

alexdavis11:05:06

There is some issue about it causing other issues https://github.com/ag-grid/ag-grid/issues/5336

alexdavis11:05:51

Maybe it will work if I trigger the fallback by enforcing CSP somehow

thheller11:05:37

nah all stuff with eval is almost guaranteed to break

thheller11:05:58

function get_" + n + "( here they are creating a function with a dynamic name

thheller11:05:12

the closure compiler will almost certainly have renamed or removed that actual function

thheller11:05:22

so it can't find it and break maybe

thheller11:05:33

no clue what this code is supposed to be doing but it looks suspicious

alexdavis11:05:36

But if I can get ag charts to go through another bundler it will be ok right?

thheller11:05:06

worth a try, since the closure compiler is definitely much more picky about certain code

thheller11:05:39

but yeah confirmed that esbuild just doesn't replace the global like webpack would

thheller11:05:48

just replacing it with window manually works fine

alexdavis11:05:18

Ok once that is working the production build does work with my minimal example, so that is good I guess. Are there any major concerns for using this double bundle/external provider approach in a big app?

thheller11:05:54

only if you intend to code split

alexdavis11:05:15

We do have a couple of modules but can probably combine them into one since it doesn't make a huge difference for our use case anyway

thheller11:05:31

cljs code still splits just fine

thheller11:05:34

just the JS code won't

thheller11:05:47

so there will always be one huge libs.js file

alexdavis11:05:01

Ahh I see, shouldn't be a problem then. So only remaining issue is I would like to use esbuild, which I guess means changing the external_boilerplate.js file in shadow, what do you think the best way to do that is?

thheller11:05:08

you can just take the original file and put it into your classpath

thheller11:05:35

so you create a src/main/shadow/build/targets/external_boilerplate.js or whatever your source path is

thheller11:05:54

and in that file replace global with window

thheller11:05:08

or check if esbuild has a flag to replace that. I'd expect it to have one

Rambabu Patina13:05:48

Hi @thheller, I am facing a compiler issue with @internationalized/date library such as

X Compilation failed.
Closure compilation failed with 1 errors
--- node_modules/@internationalized/date/dist/main.js:1169
Cannot convert ECMASCRIPT_2018 feature "RegExp named groups" to targeted output language.
And my shadoow-cljs.edn is,
{:deps     {:aliases [:dev]}
 :dev-http {8000 "classpath:public"}
 :builds   {:main {:target     :browser
                   :output-dir "resources/public/js/main"
                   :asset-path "/js/main"
                   :modules    {:main {:init-fn app.client/init
                                       :entries [app.client]}}
                   :compiler-options {:output-feature-set :es5}
                   :devtools   {:after-load app.client/refresh
                                :preloads   [com.fulcrologic.fulcro.inspect.preload
                                             com.fulcrologic.fulcro.inspect.dom-picker-preload]}}}}

thheller14:05:58

why do you set :compiler-options {:output-feature-set :es5}? that is causing the problem.

Rambabu Patina15:05:00

It is needed for our internal UI modules to work. Do we have a way to set babel or other config to recognise properly?

thheller15:05:51

> for our internal UI modules to work

thheller15:05:59

what does that mean? what error do you get otherwise?

Rambabu Patina15:05:14

We could not import the UI library, but with es5 we could able to import and consume.

thheller15:05:07

the error is telling you that a newer JS feature cannot be downgraded to :es5. so the fix is either to bump that lower limit, or not use that library. there is no other solution.

thheller15:05:31

I mean you can use something like webpack to get rid of that error, but the code will still be using that newer version of code

Rambabu Patina15:05:03

Can we compile that specific module only with webpack?, if yes could you please provide if any examples

thheller15:05:43

no, webpack either for everything or nothing

Rambabu Patina15:05:47

Ok got it. Thanks

Rambabu Patina15:05:38

Can we add the following babel polyfill as part of the shadow-cljs lifecycle hooks just before its regular compilation phase, https://babeljs.io/docs/babel-plugin-transform-named-capturing-groups-regex

thheller15:05:30

babel is not used, so no

thheller15:05:47

I mean you can always preprocess the file in the node_modules folder

Rambabu Patina15:05:40

Nice, can I preprocess the file in this location node_modules/@internationalized/date/dist/main.js Please let me know how to do it

thheller15:05:59

you run babel on that file manually

thheller15:05:02

shadow-cljs is not involved

Rambabu Patina15:05:35

Sure. Thanks much @thheller for your help!

thheller15:05:04

do you mind to explain why you need :es5? it makes no sense to use :es5, I don't get why you are using it. all this effort seems wasted on a faulty assumption that you need :es5? are you running on some historic JS engine from 10 years ago?

thheller15:05:05

there are very very few reasons to run :es5, basically only specialty JS engines. definitely not for browsers, unless you need to support like ie8?

Rambabu Patina15:05:15

There is a one react library which developed by another internal team and it's compatible to :es5/`:es6` . I personally like to use :es8 but few compatibility issues with that library. I will check with my team if they can target for :es8

thheller15:05:19

can you give an example? I mean stuff :es8 is usually compatible with all of :es5, just not the reverse? I have not seen code that worked in :es5 but not :es8 in a JS engine that supports :es8?

Rambabu Patina15:05:09

We have import statement like below ["@fuegokit/react" :as fuegokit] and (def ui-box (react-interop/react-factory fuegokit/Box)) With es8 getting

cient.cljs:23 Uncaught TypeError: app.fuegokit.ui_box is not a function
With es5/6, it displays fine by commenting one line in node_modules/@internationalized/date/dist/main.js

thheller15:05:00

none of that generates any es8 code, so the fault is likely somewhere else?

thheller15:05:41

try to (js/console.log "debug" fuegokit/Box fuegokit) before the (def ui-box ...). just to see what that object is

thheller15:05:00

also are there any other console messages? maybe an error during load?

Rambabu Patina15:05:09

One is, in.js:1499 Module not provided: module$node_modules$$internationalized$date$dist$main r

thheller15:05:47

anything else?

Rambabu Patina15:05:54

Another in.js:1499 SyntaxError: Unexpected token ',' (at module$node_modules$react_aria_components$dist$main.js:266:375)

Rambabu Patina15:05:59

I have added (js/console.log "debug" fuegokit/Box fuegokit) But nothing printing in console

thheller15:05:07

do you do any other manual processing of the code?

thheller15:05:19

the react-aria-components code works just fine?

thheller15:05:23

which browser are you testing with?

Rambabu Patina15:05:55

I am using chrome

Rambabu Patina15:05:31

The console looks

thheller15:05:12

yeah the last error is pretty much irrelevant at that point, all the others cause that one

thheller15:05:26

there should be no errors during load, the code cannot be trusted to work after the first

thheller15:05:58

have you tried disabling all chrome extensions? all looks like valid code to me, so not sure why it fails for you

Rambabu Patina15:05:51

Disabled all extensions in chrome, but having same logs

thheller15:05:27

and there is no other processing of the JS output?

Rambabu Patina15:05:01

Yes, currently no manual processing

Rambabu Patina15:05:36

just running npx shadow-cljs server

thheller15:05:13

very strange. all those packages compile and work just fine for me

Rambabu Patina15:05:40

Oh ok. I have tried with [email protected] and latest version, but not sure where it is breaking

thheller15:05:21

well 2.14 would also be a much older closure-compiler version, that could always be a problem

Rambabu Patina13:05:55

Is any configuration needed to fix it?