This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-03-22
Channels
- # alda (2)
- # announcements (1)
- # babashka (32)
- # beginners (67)
- # calva (1)
- # cider (19)
- # clerk (11)
- # clj-commons (35)
- # clj-kondo (7)
- # cljsrn (2)
- # clojure (35)
- # clojure-europe (86)
- # clojure-nl (5)
- # clojure-norway (5)
- # clojure-russia (6)
- # clojurescript (16)
- # clr (21)
- # conjure (1)
- # core-async (10)
- # cryogen (1)
- # cursive (12)
- # data-science (1)
- # emacs (29)
- # events (4)
- # figwheel-main (2)
- # graalvm (9)
- # gratitude (7)
- # honeysql (4)
- # hugsql (3)
- # hyperfiddle (23)
- # jobs (1)
- # jobs-discuss (4)
- # joyride (9)
- # malli (2)
- # off-topic (81)
- # portal (7)
- # reagent (19)
- # reitit (1)
- # releases (4)
- # shadow-cljs (121)
- # xtdb (3)
Is there a way to do this in shadow-cljs?
https://docs.sentry.io/platforms/javascript/configuration/tree-shaking/#tree-shaking-optional-code-with-webpack
Seems like somehow setting a global __SENTRY_DEBUG__
to false
and letting GCC know about it should achieve the same?
What would be an alternative?
IIRC React also does it, only it checks for the value of process.env.NODE_ENV
and not some custom constant.
Also, given that there's no comparable setting, would it make sense to implement it? Not sure how feasible it is with GCC.
I know what DefinePlugin does, but I need to see the actual code shadow-cljs is processing to comment
Sure, here's a piece of code from Sentry:
function flush(timeout) {
const client = core.getCurrentHub().getClient();
if (client) {
return client.flush(timeout);
}
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && utils.logger.warn('Cannot flush events. No client defined.');
return utils.resolvedSyncPromise(false);
}
http://unpkg.com or something, not the source file. the actual published file in the npm package
what should work is just search&replace (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)
with false
before shadow-cljs processes it
Just as a guess, tried (js* "/** define {boolean} */\nvar __SENTRY_DEBUG__ = false;")
in the first loaded ns but didn't work.
well, doing it on the CLJS parts won't do anything since they aren't compiled together
the first problem that would need solving is making it part of the code that is actually getting compiled
Ah, so the problem is that my project's code is basically appended to the NPM code that's already been processed? Those two aren't processed together?
so you can't just set a var
in one file and expect that to be available in all files
and I'm not sure the closure compiler will recognize global.__SENTRY_DEBUG__ = false;
Ah, every file. Gotcha.
And --define='__SENTRY_DEBUG__=false'
also won't work, right?
I'm not aware of a setting in the closure compiler that would be equiv to the webpack DefinePlugin
It redefines a global constant at compile-time. But if I understand the docs correctly, it would only work if there is a constant with that name.
Struggling to find a way to make the CLI work. Maybe you have a clue? Running
google-closure-compiler --module_resolution NODE \
--process_common_js_modules \
--js ./test.js \
--js 'node_modules/@sentry/**/cjs/**.js' \
--js 'node_modules/@sentry/**.json'
where test.js
is just
/** define {boolean} */
var __SENTRY_DEBUG__ = false;
but it results in
node_modules/@sentry/browser/cjs/client.js:3:13: ERROR - [JSC_JS_MODULE_LOAD_WARNING] Failed to load module "@sentry/core"
3| const core = require('@sentry/core');
^
[...]
Not sure how to tell it that @sentry/core
is one of those files.Nah, I would like to experiment a bit with the CLI first. :) Maybe there's a way to do it without hacks.
sure, have fun. can't help, never used it beyond compiling a single file without any requires
And while I'm busy wasting my time with that - Sentry also distributes ESM modules. Would that make any difference w.r.t. the original problem?
I think I was able to successfully inline the __SENTRY_DEBUG__=false
and subsequently eliminate all the blocks that used it.
However, I had to use advanced optimizations and IIRC node modules only go through simple optimizations, which does not include variable inlining.
so that it becomes if ('production' === 'production') {
and simple does eliminate that
Ahh, so it's shadow-cljs that enables that particular inlining. :)
Perhaps that inlining step could be made configurable? So people would be able to replicate DefinePlugin
by inlining whatever they want.
not sure what kind of performance impact this would have. generally not a fan of replicating every webpack feature. how much does this actually eliminate?
Not sure how to compare that properly. I can easily run one of the following:
ā¢ Advanced + inlining of false
with a subsequent elimination of the debugging lines
ā¢ Advanced + inlining of true
, so without elimination of those lines
ā¢ Simple without inlining
To properly compare with what a potential change to shadow-cljs I'd need to be able to run "simple with inlining and elimination".
> not a fan of replicating every webpack feature
Doesn't this feature sound like something that's useful in general, regardless of what webpack can do?
I gave you a couple suggestions on how you could potentially get the inlining. try them and report the results. then I might consider it. in the dark no, I don't think this is useful. JS libs are riddled with these non-standard webpack specific things
The first 2 options, when compared, have a difference of 3% in size: 32693 vs 33605. But it's just this particular case, for the particular files that I checked - not the whole of Sentry, far from it. > try them and report the results Sure, what's up?
12405 vs 12738. I'm wasting my time on the concept, not on the size. :) In the process, I'm learning more about GCC and how different things work. It would be more interesting to compare the sizes of the whole of Sentry. Not sure how hard that would be.
Well, definitely harder than adding a bunch of files to the CLI arguments - started getting Inline JSDoc on default parameters must be marked as optional
errors, no clue how to proceed, but probably not going to.
cd node_modules/@sentry/browser; find . -name "*.js" -type f -exec sh -c 'echo "\nconst __SENTRY_DEBUG__=false;" >> "$0"' {} \;
With this:
(ns hgs.x
(:require ["@sentry/react"]
["@sentry/integrations"]
["@sentry/replay"]
["@sentry/tracing"]))
(defn main []
(js/console.log 0))
and a similar setup I get gzipped sizes of 106388 and 111964. So ~5%.Mere 100 kB for me to be able to never ask a user to record a video - sign me up! And that's just one of the features.
Heh, according to a shadow-cljs report my own sources + CLJS in that particular project go well beyond 2MB ungzipped. So yeah, I'm not too concerned about 100 kB at this point. :) Let alone 5% of 100 kB. I'm simply curious whether it's a change that would be worthwhile to have at the tool level, for everyone.
Fair! Hmm, was sure I saw something similar in Vega and MUI, but apparently not - can't find it in the docs. In any case, seems like there's a clear way forward if that feature becomes needed. I'd like to work on it myself although of course can't provide any time estimates at the moment.
FWIW I thought about this a bit. its definitely not just a simple replacement. since (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)
would become (typeof false === 'undefined' || false)
which doesn't do what you'd want š
š I'm running into a bug with :esm
and a side-effecting library. My shadow config looks like:
{:target :esm
:js-options {:js-provider :import}}
and in my cljs, I have
(:require ["quill-mention"])
(the package executes a side-effect)
If I do (:require ["quill-mention" :as foo])
and add a (js/console.log foo)
my code works, but when I remove the log it the library isn't included. Note, this change only started occurring after 2.20.12
. Would it be helpful to create a minimal reproducible example or any quick ideas as to what the issue might be?hmm :import
means shadow-cljs just emits import * as X from "quill-mention";
for that require?
ahhh, let me check. just realized i was looking at webpack generated code so this might be an issue with the webpack bundling instead of shadow
Looks like if I grep for quill-mention
in the shadow generated code it's not present (when I require it as (:require ["quill-mention"])
. However, when I use (:require ["quill-mention" :as foo])
and console log it ( foo
), then quill-mention
is included in the bundle as expected.
If you'd like, I can create an issue for it and then look into it in a bit Edit: created https://github.com/thheller/shadow-cljs/issues/1102
I'm weirdly having some issues with hot reload at the moment. I've been using this successfully for years, but I'm not sure what changed. I have some functions marked with :dev/after-load
and they aren't being called upon reload. Any idea how I might begin to debug this ?
There are a couple of build warnings, but not from shadow-cljs itself, so I don't imagine that should matter.
I wouldn't expect some warning from a function that a library deprecated would just make reloading stop working, with no logging or anything. It's a legitimate decision, but I think it's funny to act like no one would be surprised by this.
Maybe I didn't explain well - I know what the warnings were from - just not always how to resolve them. So in this case, I was ignoring a deprecated function warning because I don't know how NOT to use that function at the moment (reagent.dom/dom-node) ... I was just surprised when that made shadow-cljs not reload things any more.
don't know where that came from. I'm not surprised that you didn't know this setting, why would you
it doesn't reload because it may break stuff. some warnings will actually lead to runtime errors when trying to run it anyways
Yeah ... and I'm reluctant to ignore these warnings or turn them off for that very reason.
Hey, I'm interested in adding some Reagent components to an existing PHP codebase. I got it working yesterday by outputting the compiled JS into the assets directory served by Apache, but that's outside the cljs project root. It breaks the ws connection for watching the build. Is there a way to keep the watch running but output code outside the project, or should I just create a project in the PHP assets dir?
I do not understand that description. what does a WS connection have to do with where the output lives?
I'm not sure myself. I just know that when I open the page in the browser the console warns me that shadow cljs can't connect.
No same domain, but actually ignore me, it works now. Thanks.
Idk what changed between yesterday and today.