This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-02-26
Channels
- # announcements (19)
- # babashka (27)
- # beginners (24)
- # calva (14)
- # clerk (5)
- # clj-commons (21)
- # clojure (51)
- # clojure-europe (14)
- # clojure-madison (1)
- # clojure-nl (1)
- # clojure-norway (9)
- # clojure-uk (4)
- # clojuredesign-podcast (32)
- # core-async (14)
- # datomic (7)
- # events (1)
- # honeysql (3)
- # hyperfiddle (14)
- # introduce-yourself (2)
- # kaocha (7)
- # malli (21)
- # off-topic (50)
- # portal (2)
- # reagent (41)
- # reitit (41)
- # releases (1)
- # scittle (6)
- # shadow-cljs (90)
- # tools-deps (10)
- # xtdb (1)
- # yamlscript (1)
Hello Everyone!
I am working on a project and am trying to setup code splitting using modules. I have create multiple modules that are dependent on each other but when I create the final optimised build, I see my Main.js file has a huge crore.cljs
file of ~400KB, and I see that it has included dependencies for the lazy loaded components too. shouldn't it only load dependencies for the main module and rest should be loaded later on demand?
Adding the screenshot of my report and my shadow.cljs file code below.
;; shadow-cljs configuration
{
#_ (deps true allows shadow CLJS to load the dependencies
from deps.edn file "")
:deps true
:dev-http {3000 "public"}
:nrepl {:port 5432}
:builds
{:base-app
{:target :browser
:module-loader true
:modules {:main {:entries [base-app.core]
:init-fn base-app.core/init}
:data-table {:entries [fms.components.data-table]
:depends-on #{:main}}
:fleet-create {:entries [fms.views.fleet.create]
:depends-on #{:main}}
:login-page {:entries [auth.views.login]
:depends-on #{:main}}
:home-page {:entries [home.views.home]
:depends-on #{:main}}
:fms-base-page {:entries [fms.views.base]
:depends-on #{:home-page}}
:fms-fleet-list-page {:entries [fms.views.fleet]
:depends-on #{:home-page}}
}
:build-hooks [(shadow.cljs.build-report/hook)]
:compiler-options {:externs ["datascript/externs.js"]
:optimizations :advanced
}}}}
@U05224H0W Can you help how to optimise this and make the bundle size smaller?
first you should figure out why cljs/analyzer.cljc
is there. this should not be there unless its a self-hosted build
https://code.thheller.com/blog/shadow-cljs/2019/03/03/code-splitting-clojurescript.html
if you send me the full report I can make some suggestions, but going off screenshots this is going to take years
the gist is that if everything depends on :main
then ALL code the modules share can only go there
and the screenshot you highlighted only shows which namespaces required cljs.core, which is all of them. so it is not a useful thing to look at and doesn't mean anything regarding splits
SO basically its like I have a main page, which lazily loads all other routes, hence I have added them as dependency. As also suggested here https://pitch-io.github.io/uix/docs/code-splitting.html
@U05224H0W here is the entire report file
suggestion #1 to shrink the app: remove reitit or at the very least reitit-coercion. it brings in cljs.analyzer which it shouldn't
if you scroll down you'll see that the :login-page
module is tiny, as well as the :fleet-create
Yes, that I saw, so the pages are small, I am using Reitit for routing, not sure how to remove it. Show is lazy load Reitit too?
just the coercion part. I don't know what that is or how to remove it, but it contributes over 200kb to the build. I would remove it entirely due to that.
I agree, I was thinking of using react-router but reitit was more idiomatic way suggested hence used it.
sorry I cannot give you any advice on which router to use. I have not used anything react based for 5+ years
if you only use reitit for routing then the build size it contributes is absolute overkill
the way I treat "routing" is that there is a function that parses the URL path, and makes db data out of that. but I can't quite tell how you handle state, so that might not work in your system
your build config has datascript/externs.js? but you don't appear to be using datascript?
doesn't contribute to build size, so nothing to worry about. just something you can probably remove
yes, I just commented out Datascript to check how much size is reduced. the problem is, with time I will be using more of these libraries to complete my project. So I am not getting a clear idea of how to maintain my JS bundles small. Like datascript add 200KB to the app, now how will I add this library in future while maintaining the file size
given that reitit is almost from 25% of your build I'd start there. for a router that seems excessive
so is the a way where we can lazy load npm modules, while the main.js app load initially with js and then these npm libraries are added when needed
(and are also required by base-app.core
directly for the most part, so cannot move elsewhere
but as I said the biggest chunk of :main
that could potentially be removed is reitit and its dependencies
I cannot see your code ... so I can only give you advice based on what I see in the report
apart from the 2 tiny modules that don't really need to be modules it looks fine as far as splitting goes
@U05224H0W I understand reitit and will try to remove it. but why is core.cljs showing other modules also in the dependency.
If you want, I can share the code with you too, give me your github handle, I will add you to the repo
I don't know what you mean, your screenshot is showing two lines without context of where they are
Yes, That's what I am speaking, when I hover I see all the lazy loaded modules.
yes, this is fine. it does not mean they are in the :main
module. it tells you why they are in the build at all
so check cljs/analyzer.cljc
, you'll see that it comes in via reitit, which was required by your base-app.core
Does :loader-mode
have a function anymore in shadow-cljs.edn
?
Looking for docs….
:devtools {:loader-mode :script}
in the build config. only ever had any effect in the :browser
target
I’m cleaning up our build configs, and trying to consolidate and remove cruft or obsolete stuff.
Does :devtools
belong on the same level as :dev
or nested inside it?
Oh great!
That would be great, thank you. Just here in this thread?
ok one sec
:builds {:mp360 {:target :browser :js-options {:resolve {“moment” false ##“react” {:target :npm :require “preact/compat”} ##“react-dom” {:target :npm :require “preact/compat”} “jquery” {:target :global :global “jQuery”}} :ignore-asset-requires true} :devtools {:preloads [http://doublethedonation.dev day8.re-frame-10x.preload.react-18 devtools.preload] ;;:loader-mode :eval :after-load http://doublethedonation.integrations.app/dev-reload! ##:console-support false} :dev {:compiler-options {:closure-defines {re-frame.trace.trace-enabled? true day8.re-frame.tracing.trace-enabled? true}}} :release {:build-options {:ns-aliases {day8.re-frame.tracing day8.re-frame.tracing-stubs}}} :modules {:mp360 {:entries [http://doublethedonation.integrations.app]}} :output-dir “resources/public/js” :asset-path “/api/js” :build-hooks [(shadow.cljs.build-report/hook {:output-to “mp360_report.html”})] :compiler-options {:infer-externs :auto :closure-defines {re-frame.trace.trace-enabled? true day8.re-frame.tracing.trace-enabled? true}}}
Here’s the relevant bit I’m working on.
ok cool, thank you. I was hoping to remove anything that just cluttered it up.
Yeah, I thought so as well.
Correct. The tracing is new, I asked the CTO if I could roll it into our build file so I don’t have to stash it locally, since I’m the one that uses it most often.
Really all that’s left are loader-mode
, autoload
, and enabled
.
:loader-mode
you can generally remove unless you have a very specific reason you are setting it to :script
Ok I figured, because we have a separate ‘plugin’ build I did not include that is not a SPA, so hot-reload doesn’t make sense.
The takeaway is I can remove :loader-mode
and consolidate :compiler-options
and everything else is good to go.
Thanks!
I'd like to find every access to JS globals js/*
in my codebase. Does shadow-cljs helps me with that? somewhere in build report?
i did grepping but I was a bit worried if my grep misses something.
There is no syntax other than js/
, right?!
I broke production this morning because of an misspell in js/
access
I'm looking for alternatives to avoid this type of problem
I think that #CHY97NXE2 may be my path
Warn when a new
js/*
var-usage appear
our jsBundleGlobals.js
is deprecated and don't have new fields anyway
anyway, thank you @U05224H0W