Is it possible to use Rescript with Qwik?

Qwik looks very enticing and I wonder if it could work with Rescript.

1 Like

Might be helpful if you outline what makes it not work today.

sadly I just stumbled upon it today so I don’t know the ins and outs.

so far I think it would be tricky to implement the setState which they do with a mutation instead of setState

example of a counter:

import { component$, useStore } from '@builder.io/qwik';

export const App = component$(() => {
  const store = useStore({ count: 0 });

  return (
    <div>
      <p>Count: {store.count}</p>
      <p>
        <button onClick$={() => store.count++}>Click</button>
      </p>
    </div>
  );
});

Now, I have no experience with Qwik, but the counter example seems doable in ReScript to me:

module Qwik = {
  @module("@builder.io/qwik")
  external component: (unit => React.element) => unit = "component$"

  @module("@builder.io/qwik") external useStore: 'a => 'a = "useStore"

  @deriving(abstract)
  type buttonProps = {
    @optional @as("onClick$") onClick: unit => unit,
    @optional children: React.element,
  }
 
  let button: React.component<buttonProps> = %raw(`"button"`)
}

type store = {mutable count: int}

let make = Qwik.component(() => {
  let store = Qwik.useStore({count: 0})
  <div>
    <p> {React.string(`Count: ${store.count->Belt.Int.toString}`)} </p>
    <p>
      <Qwik.button onClick={() => store.count = store.count + 1}>
        {React.string("Click")}
      </Qwik.button>
    </p>
  </div>
})
1 Like

You piqued my interest, so I took a stab at making Qwik work with ReScript. Unfortunately, it seems very difficult to do at the moment.

First of all, Qwik is built on top of JSX, but doesn’t actually use React. That means my example above wouldn’t work. It seems to be the same problem as using SolidJS with ReScript (https://github.com/Fattafatta/rescript-solidjs#background), so until we have a preserve option for JSX, solving this seems to require some exotic solutions.

Second problem I ran into is the Qwik Optimizer (Optimizer Rules - Qwik). It performs static code analysis and does some transforms depending on how functions are named and called. For example, it expects your components to be written like this:

import { component$ } from “@builder.io/qwik”

component$(() => {
  // return JSX
})

But ReScript never destructures imports, so trying to write the same in ReScript generates this:

import * as Qwik from “@builder.io/qwik”

Qwik.component$(() => {
  // return JSX
})

While the code is functionally the same, the Qwik Optimizer fails to transform the second example. You could probably resolve this by importing using %%raw, but that is far from ideal.

So my current verdict is that it is unfortunately not very feasible to use with ReScript at the moment. Perhaps in the future, when both Qwik and ReScript JSX have matured a bit.

2 Likes

Nice investigation! In my opinion, point 1 about JSX preserve mode is what matters. Point 2 is hopefully something that could be PR:ed directly to Qwik, as in allow for both named and “all” imports.

3 Likes