v3.ocaml.org-rescript icon indicating copy to clipboard operation
v3.ocaml.org-rescript copied to clipboard

Reduce large assets

Open cdaringe opened this issue 2 years ago • 7 comments

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

image

cdaringe avatar Aug 30 '21 03:08 cdaringe

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.

ghost avatar Aug 30 '21 05:08 ghost

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

cdaringe avatar Aug 30 '21 06:08 cdaringe

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!

ghost avatar Aug 30 '21 07:08 ghost

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).

patricoferris avatar Sep 07 '21 23:09 patricoferris

I like that you clarified that the output was generated by Rescript and Patrick (:.

ghost avatar Sep 07 '21 23:09 ghost

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.

ghost avatar Sep 22 '21 13:09 ghost

$ 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) oc-sq-lg

$ convert oc-sq-full.jpeg -resize 400x400 -strip oc-sq-sm.jpeg

<20KB

oc-sq-sm

will try and get a pr goin soon

cdaringe avatar Dec 17 '21 09:12 cdaringe