melange-re / melange

A mixture of tooling combined to produce JavaScript from OCaml & Reason
https://melange.re
Other
846 stars 52 forks source link

dynamic imports #762

Closed joprice closed 2 months ago

joprice commented 1 year ago

Large applications can benefit from loading subsets of the app dynamically. Scalajs has enabled this with a builtin that triggers the compilation of a separate module imported at runtime: https://www.scala-js.org/doc/project/module.html#dynamic-imports. Could something similar be possible in melange?

joprice commented 1 year ago

I found an issue on reason-react mentioning this and was able to write a ppx that wraps a module in the lazy wrapper shown here https://github.com/reasonml/reason-react/issues/498#issuecomment-559820760. So it seems that melange is handling dynamic imports well enough via externals, but I'm curious about the concerns around the allowDynamicImports suggestion. I'd like to try to repro an example that reproduces this, but unsure in what situations optimizations like that could kick in.

jchavarri commented 1 year ago

@anmonteiro and I were discussing just yesterday that it could look st like:

let x: _ Js.Promise.t = Js.import(module Foo)

But I'm afraid we'd have to introduce some ppx so that the compiler can recognize these as particular modules, and not regular ones. Maybe we can combine this issue with the bindings rfc in #777 and do something like this:

let%js.import x = (module Foo)

Or for particular values:

let%js.import x = Foo.bar

The compiler would distinguish the kind of import through the payload: if it's a string, it's a "traditional" import, if it's a first-class module or an identifier, it's a dynamic import.

So it seems that melange is handling dynamic imports well enough via externals, but I'm curious about the concerns around the allowDynamicImports suggestion.

Maybe we could look into how ReScript solved it, they don't seem to require any annotations in files: https://rescript-lang.org/blog/first-class-dynamic-import-support

texastoland commented 1 year ago

In case it helps: rescript-lang/rescript-compiler#5703

jchavarri commented 1 year ago

For completion, this is an experiment i did with bucklescript, ages ago: jchavarri/reason-react-lazy-loading/PdfPreviewLazy.re#L19.

It was working, but it required some magic and cumbersome tricks to prevent the compiler from including the lazy module in the main bundle.

pedrobslisboa commented 2 months ago

I am pasting it here for anyone else who is following this issue: dynamic import #1164