Using dynamic imports in NextJS

Hi everyone!

I’m trying to optimize my bundle size in a project based on NextJS and ryyppy bindings in particular. I’ve got a fat component CdekWidget (done in ReScript) that would be better to load later. So, I’m going to use the NextJS dynamic import.

I’ve done it before in the JS-land, but in this case I’d like to stay in ReScript. So, here what I’ve got:

module DynamicCdekWidget = {
  let makeProps = () => Js.Obj.empty() // <- 1
  let make = {
    open Next.Dynamic
    dynamic(
      () =>
        import_("./Static/CdekWidget.bs.js") // <- 2
        ->PromiseX.map(x => x["make"]), // <- 3
      options(~loading=() => <MaterialUi.CircularProgress />, ~ssr=false, ()),
    )
  }
}

// Later use <DynamicCdekWidget /> as a regular component

This works fine. Problem solved. However, I see three annoyances here, marked as 1, 2, 3. And I’m not sure that’s the canonical way to go.

  1. Since I don’t use @react.component here, I have to define makeProps for myself. Looks like a boilerplate
  2. Here I should know the exact path to .bs.js. I suspect this is inevitable, but who knows, perhaps some magic possible to just mention a module name and the path comes out automatically
  3. I have to tweak the import result since ReScript components don’t provide the default export (aren’t they?). Not a big problem, but boring.

In summary, this works, but looks much more bloated then the plain-JS version which is one-liner basically. So, I wonder, am I doing it right?

This will become easier with ppx V4, but I guess not in all aspects.
Would you add to the V4 issues to think about this too?
Dynamic imports are definitely something needed regularly and so far they have received limited attention.

JSX V4 will solve 1, as it removes makeProps all together.

Point 2 is something we should definitely have support for in the compiler, and there’s a couple of issues for it already on the tracker. This would be a good thing to focus on soon imo, as it would solve a quite painful problem. I’m unsure however how complex it would be to implement.

Point 3 can be solved by a simple let default = make in the component file, right…?

I’m hoping that the end solution for how to use dynamic imports in ReScript can end up at least as ergonomic as in TS, perhaps even more ergonomic as we can potentially make the module identifier itself be what you refer to when importing, rather than needing to know the full file path to the. But this all remains to be seen/discussed of course.

3 Likes

Easy https://github.com/rescript-lang/rescript-compiler/issues/5593

1 Like