boot-clj / boot-cljs

Boot task to compile ClojureScript programs.
Eclipse Public License 1.0
176 stars 40 forks source link

Code-splitting in :advanced includes all the code #185

Closed DjebbZ closed 5 years ago

DjebbZ commented 6 years ago

Hello,

When code-splitting in :advanced boot-cljs still produces one js file for each cljs/cljc namespace and the files as specified in the :modules compiler options, whereas it's not needed at all and should produced only files as specified in :modules. The extraneous files are still usefull in :none and :whitespace as they're downloaded one-by-one. Not sure about :simple.

To be clear: code-splitting in :advanced mode does work, just produces too much files.

Deraen commented 6 years ago

Do you have .cljs.edn file?

DjebbZ commented 6 years ago

Changing the title of the issue since it's not working at it should at all.

I have a classical website served by the server, not a single page app. We decided to reduce the js bundle size we serve with a double solution:

  1. create :modules with code-splitting to lazy-load some code only when needed in the page
  2. create a js bundle for our different pages ("universes" really, roughly 2 ou 3 different js bundles is enough to cover everything)

Number 1 alone works, so that apart from the code the should end up in the split, everything is in :cljs-base. It's only supported with a .cljs.edn file though (see #183), but so far so good.

Now I want to create one these page bundles. So I removed several code from our initial single entry point namespace, remove several requires, etc. It doesn't work, the produced bundle still includes all the code from all the namespaces (apart from the split modules of point number 2).

This is how I did it. I created a mypage.clsj.edn, that looks roughly (shortened for brevity) like this:

{:require          [myproject.mypage]
 :init-fns         [myproject.mypage/init]
 :compiler-options {:libs       ["some/internal/lib.js"
                                 "..."]
                    :output-dir "js"
                    :modules    {:cljs-base        {:output-to "js/mypage.js"}
                                 :lazy-load-me-plz {:entries   #{myproject.lazy-load-me-plz}
                                                    :output-to "js/mypage.out/lazy-load-me-plz.js"}}}}

js/mypage.js include everything apart from the code of the myproject.lazy-load-me-plz, whereas it should include way less code.

I though at first that splitting some of the cljs task options in the .cljs.edn file and the build.boot didn't work, so I added everything in the .cljs.edn file and used a simple (cljs) in the build.boot. Not working.

I also decided to manually specify the entry point as a :modules, so I added :my-page with :entries #{myproject.mypage}. Not better, in this case the js file for this new entry was rather small but still too much code in the file for the :cljs-base file (again, everything apart from the split modules).

Note that I did all the tests in :none and :advanced. I completely understand the difference between both. I was expecting :advanced to include just what I specificed from the entry point (:require in .cljs.edn).

This is a blocker for us, as we need to reduce our bundle size. I think it's because whatever I tried all namespaces are required and the corresponding code end up at some point in one of the specified js file. I think that even in :none only the namespaces necessary for the page bundle should be compiled, not every namespace of my app.

I hope I'm clear. I'm open to help you as much as I can to resolve this problem.

-- edit: fix some typos

DjebbZ commented 6 years ago

My bad, it looks like the problem comes from our code. One of our namespaces required unwanted stuff, so we just need to split it better. I'll report after trying.

DjebbZ commented 5 years ago

As I said in another issue, I managed to get it working very recently. Closing.