v3.ocaml.org-rescript
v3.ocaml.org-rescript copied to clipboard
Reduce large assets
Problem
- camel image needs to be compressed
- bundle JS is enormous for static content. looks like all of the tutorials are inlined, and more. finer module resolution is likely needed for each per-page next.js compilation
bundle JS is enormous for static content. looks like all of the tutorials are inlined, and more. finer module resolution is likely needed for each per-page next.js compilation
Without looking into the specifics of this bundle, my first reaction is to wonder whether keeping the data in OCaml modules (which ultimately become javascript modules) ends up hurting the built in mechanisms for data splitting. So, although getStaticProps may only produce one tutorial's worth of data at a time, something in the Tutorial.make
function is still referencing the OCaml module and webpack's tree shaking is not eliminating the OCaml module as a runtime dependency. If that turns out to be true, then we can modify the implementation of Tutorial.make to avoid referencing the OCaml module's functions.
I’ll have to take a peek later, but iirc when I popped open the tutorial JS module, it was not ESM. We need each tutorial exported as a top level ESM export and Tutorial.make to produce a specific symbol import for the relevant page, and we should be set
I am hoping we can avoid that, since anything that is only referenced in getStaticProps is not supposed to be included in the generated bundle.
I am hoping the solution ends being that we just need to define one more data type that knows how to access the Ood.tutorial fields, but isn't defined within the generated ocaml modules. We'll see!
Thanks for reporting this @cdaringe and @kanishka-work, quick disclaimer I'm not super familiar with the JS/ES6 world but I did a little bit of digging on this.
Ultimately I think the problem is stemming from the Pages.Make/Pages.MakeSimple
abstraction. If you revert back to f9444c8a01a3bd40a8509770c4a705ce0d1ec09c
when we were still writing things by hand (see https://github.com/ocaml/v3.ocaml.org/blob/f9444c8a01a3bd40a8509770c4a705ce0d1ec09c/pages/resources/%5Btutorial%5D.res) afaict there is no problem with the large bundle sizes. I'm assuming somewhere in the functor application and including it into the file means webpack (or nextjs) can't do the tree-shaking properly?
I inlined all of the Pages.MakeSimple
code (see this gist https://gist.github.com/patricoferris/1e2b9c0d9c6be344f06cadc088560f9f), you can run make build
then copy this over the top of the generated [tutorial].js
file and run npx next build && npx next export && cohttp-server-lwt out
then have a look for the large bundles (I think they're gone but note we're still importing everything from ood
).
I like that you clarified that the output was generated by Rescript and Patrick (:.
If we pursue this further, I would remove the page functor temporarily, and then design a new page functor slowly and measure the performance impact after each commit.
$ convert oc-sq-full.jpeg -resize 800x800 -strip -define jpeg:extent=50KB oc-sq-lg.jpeg
github didn't reprocess it too much, at approx 48KB (96% reduction)
$ convert oc-sq-full.jpeg -resize 400x400 -strip oc-sq-sm.jpeg
<20KB
will try and get a pr goin soon