ReScript Modules
Recently, I’ve been investing quite a lot in learning ReScript, and TBH, I’m pretty much dead as a JS developer because I’ve seen the better world. Much better one.
As a part of the “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 will be almost Twitter-like shout-outs about the features I’m excited about the most.
Ok, the first one is definitely about modules. It seems this is the number one thing that confuses most newcomers from the JS world (I was there!), so let’s start with it.
Each .res file is a module
Let’s say you created a new file–Math.res
. Boom, you have a new module in your app called Math
.
By convention, all filenames are capitalized to match a module name. You can name a file math.res
, but the module name is still capitalized: Math
.
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 the module’s consumers using dot notation.
let sum = (a, b) => a + b
// Now you can use `Math.sum` in another module
All modules are available globally
Let’s say you created a file App.res
and want to use the sum
function from the Math
module. 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 them without messing with imports.
let onePlusTwo = Math.sum(1, 2)
Imagine when you implement some UI where you need a Button
, Input
, Link
, etc. Every time you need a new component in JS, you have to go up, import it, then 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 start using it, you’ll get how brilliant this is.
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 are 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). The compiler backs you up in case you accidentally create a file with a non-unique name.
Initially, it might seem an inconvenient constraint, but in reality, it makes naming your modules accurate and explicit across the entire app.
E.g., in JS, you can easily get into this state:
export default AuthButton extends React.Component {}
import Button from "./LoginButton";
What a mess! If you ever decide to rename your component, you must change all these places to keep your naming accurate. Meh. In the ReScript world, you have only one source of truth: a file name. So it’s always guaranteed to be accurate across the entire app.
More about the ReScript modules in the official documentation.