ReScript Modules
Recently, I’ve been investing quite a lot in learning ReScript and TBH I’m pretty much dead as JS developer right now because I’ve seen the better world. Much better one.
As a part of “Selling ReScript to my colleagues” campaign (and to anyone, really), I’m going to spam your feeds from time to time with ReScript related write-ups (hopefully, plural!). I’m too lazy these days to do epic monolithic posts so it’s going to be almost twitter-like shout-outs about the features I’m excited about the most.
Ok, first one is definitely about modules. It seems this is the number one thing that confuses the most of newcomers from JS world (I was there!) so let’s start with it.
Fact #1: Each .res file is a module
Let’s say you created new file Math.res
. Boom, you have a new module in your app called Math
.
By convention, all filenames are capitalized to match module name. You can name file
math.res
but module name is still capitalized:Math
.
Fact #2: All content of a module is exported by default
If you create a type or a function or whatever inside your module it’s automatically available for module’s consumers using dot notation.
let sum = (a, b) => a + b
// Now you can use `Math.sum` in another module
Fact #3: All modules are available globally
Let’s say you created file App.res
and want to use sum
function from Math
. How can you import it? The answer is “You don’t need to!”. All your root modules are available everywhere in your app. You can use any of them once you need it without messing with imports.
let onePlusTwo = Math.sum(1, 2)
Imagine when you implement some UI where you need Button
, Input
, Link
etc etc: every time you need a new component in JS you have to go up, import it, go back to where you were. With ReScript, you can just use whatever you want right here right now without interrupting your flow. So good! Once you’ll start using it, you’ll get how brilliant this is.
Fact #4: No folders (for the compiler), all filenames must be unique
Of course, you can use folders to group your files as you usually do, but for the compiler, all your files within a project is a flat list of modules. So all your files, no matter where they are located, must have unique names (remember, all modules are available globally). Compiler backs you up in case you accidentally created a file with a non-unique name.
At the very beginning, it might seem inconvenient constraint but in reality, it makes the naming of your modules accurate and explicit across the entire app.
E.g. in JS you can easily get into this state:
// LoginButton.js
export default AuthButton extends React.Component {}
// LoginForm.js
import Button from "./LoginButton";
What a mess! If you ever decide to rename your component you have to change all these places to keep your naming accurate. Meh. In ReScript world, you have only one source of truth: file name. So it’s always guaranteed accurate across the entire app.
More about the ReScript modules in the official documentation.