Avoid duplication of code in js_of_ocaml output

I’m developing a web application using js_of_ocaml. Some of my app’s pages include several javascript files generated by jsoo, like:

<script src="/js/file1.js" type="text/javascript"></script>
<script src="/js/file2.js" type="text/javascript"></script>
<script src="/js/file3.js" type="text/javascript"></script>

These files are generated using individual dune executable stanzas, so each file is produced independently. These executables have some common dependencies in libraries stanza of each dune file, so I guess that the same code is actually inserted several times on the same web page. I’d like to eliminate this redundancy and reduce the size of loaded javascript files. They are actually ~800-1000KB each using release profile for compilation. I can barely accept such size for one js dependency, but when it comes to several dependencies 1MB each, there are problems :slightly_smiling_face:

I heard something about separate compilation for js_of_ocaml, but not sure if this is relevant. The only solution I see is to extract common dependencies and jsoo runtime into a single file (or some separate files) and include it to the web page, but I have no idea whether this is possible at all.

Can anyone give an advice on how to handle this?

UPD.
Here is my dune file for one of the generated js files:

(executable
  (name       scaffold)
  (libraries  components)
  (preprocess (pps js_of_ocaml-ppx)))

components is my GUI library for client-side usage, which has the next dune file:

(library
  (name       components)
  (libraries  js_of_ocaml
              js_of_ocaml-lwt
              js_of_ocaml-tyxml
              components_tyxml)
  (preprocess (pps js_of_ocaml-ppx)))

components_tyxml is my GUI library for server/client side usage, with the following dune file:

(library
  (name      components_tyxml)
  (libraries str tyxml color))

The resulting scaffold.bc.js has 8.5MB in dev mode and 332KB in release mode. It is very simple, so not so large as other js files I’ve described above.
The problem is that components library is a dependency for every other js executable, so it is actually loaded as many times as the number of js files.

3 Likes

Why not do the js_of_ocaml in your final executable and leave your library components as pure ocaml?

In the provided example, js executable is produced only for scaffold target, components library is pure OCaml and is mentioned as a dependency for the target (and for other targets not shown in the example).
I can’t compile only one js executable per web page as the list of included javascript files is formed by the server and may vary. The idea itself is that the web page has tabs for navigation and tab list is variable. Rendering of each tab is handled by its own script. List of shown tabs is determined by the server, so it inserts appropriate js scripts to HTML dependent on available tabs.