Give your feedback about rescript-webapi!

Hello everyone,

We know the current situation around WebAPI in rescript is not ideal and we would really like to improve it.

Please give your feedback about rescript-webapi, tell us the things that work, the things that don’t, how would you make things ideally if you could rewrite everything from scratch. Think about it in a broad way, not just the API but also the documentation, the discoverability, the editor support, etc!

Thanks a lot!

3 Likes

I’ll briefly summarize the points that already got reported:

  1. the existing API is too far from the JS one (from window.location.origin in JS to Webapi.Dom.window->Webapi.Dom.Window.location->Webapi.Dom.Location.origin in rescript)
  2. we could change the types to base them on private spreaded records instead of abstract types, this would play well with simple and imperative APIs (this would allow to write window.location.origin in rescript as well), but could cause issues with more polymorphic/dynamic APIs (how would we write multiple bindings of the same JS function?).
  3. we could improve the current bindings by making use of features from >= v11 (multiple optional arguments to replace several bindings)
  4. we could improve the inheritance modelling (type spreading and coercion could be a solution) that is quite a pain right now
  5. we could add docstrings and examples to have top notch API doc like Core has
  6. we could improve the editor tooling and Core to improve discoverability/DX
  7. we could ship rescript with @rescript/webapi directly
  8. or ask a question in create-rescript-app to include the relevant bindings (webapi, node, deno, bun)
4 Likes

Just reiterating things already mentioned here, but ergonomics is the most important here I think. Like mentioned, it’s a world of difference between doing:

Webapi.Dom.window->Webapi.Dom.Window.location->Webapi.Dom.Location.origin

and doing:

window.location.origin

And even if we could make the argument that the first one is “more correct/idiomatic” in our world, it’s just not good enough ergonomics wise, in my opinion.

I think one of the biggest issues I’ve experienced with Webapi is that it’s so different to how you’d use the same things in JS. The big problem for me with that is that my general knowledge with how to work with the DOM doesn’t translate fully to ReScript. And that creates a scenario where I’m significantly slower.

6 Likes

My two cents:

  • Most people that will use this API will have existing JavaScript knowledge, so the spreaded record idea would make this a lot closer to what people are familiar with.
  • I would organize all the modules as they are listed on Web APIs | MDN. And really try to go broad and include the Fetch API for example.
  • From a tooling point of view it would be great if we could autocomplete a list of functions that take the current type as first argument when people press ..
    The list should show ->someFunctionX, ->someFunctionY and just mimic what folks expect to find when they would dot into the object.
  • We should strive for an easy to contribute process with frequent automated releases. For example, contribute a fix + changelog entry => publish to npm via CI.
4 Likes

What is the desired way to call these?

// Nested modules
WebApi.Navigator.cookieEnabled

// An object
WebApi.navigator.cookieEnabled


// If you have WebApi open it could match JS
navigator.cookieEnabled

I think the first one looks more like ReScript code, but the second one would match the web api docs.

I ran into the same question when writing our jest bindings - is it Jest.Fn.make(), Jest.fn() or jest.fn()?

My vote would go for Navigator.cookieEnabled. It has the same ergonomics but is namespaced nicer. As much as I like the direct navigator.cookieEnabled, when you need to add function bindings the former makes it more clear where you can look for those functions (i.e. Location.assign)

1 Like