Skip to content

Commit c4ca3a9

Browse files
committed
How ReScript Compilation Works
1 parent b0faae6 commit c4ca3a9

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

_blogposts/2025-11-11-introducing-rewatch.mdx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,32 @@ The rewrite also opens doors for future improvements that require tight integrat
8484

8585
ReWatch takes a fundamentally different approach to building your code. At its core is a sophisticated understanding of what actually needs to be rebuilt when files change. Let's break down how it works.
8686

87-
### Understanding CMI Files: The Foundation
87+
### How ReScript Compilation Works
8888

89-
Before we dive into ReWatch's innovations, it's worth understanding a key concept: CMI files.
89+
Before diving into ReWatch's optimizations, it helps to understand ReScript's compilation model, which differs from many other languages.
9090

91-
**CMI stands for Compiled Module Interface.** When the compiler processes your ReScript code, it generates several output files:
91+
**ReScript compiles one file at a time, in complete isolation.** When you compile `Button.res`, the compiler doesn't maintain any shared state with other modules. Each file produces its own self-contained set of artifacts: the JavaScript output (`.mjs`), the module interface (`.cmi`), the typed tree (`.cmt`), and optimization metadata (`.cmj`). There's no separate linking phase like in C/C++, and no whole-program analysis like in many bundlers.
92+
93+
Compilation happens in two phases: first, the file is parsed into an abstract syntax tree, then that tree is type-checked and compiled to JavaScript. This two-phase approach gives ReWatch fine-grained control over what work to skip. If a file hasn't changed at all, both phases can be skipped. If a dependency's public interface didn't change (even though the file was modified), dependent modules can skip recompilation entirely.
94+
95+
Additionally, ReScript's module system enforces a strict constraint: **dependency cycles aren't allowed.** You can't have Module A depending on Module B while Module B also depends on Module A. This means the module graph is always a DAG (Directed Acyclic Graph).
96+
97+
Think of it this way: most languages compile like cooking a complex dish where all ingredients affect each other. ReScript compiles like an assembly line where each station produces a complete, independent part. This makes it straightforward to parallelize, cache, and optimize.
98+
99+
**Why this matters for build performance:**
100+
101+
- **Perfect caching:** Since files compile independently with no global state, cached artifacts are always safe to reuse
102+
- **Trivial parallelization:** No coordination needed between parallel compilations since they don't share state
103+
- **Precise incremental rebuilds:** Changes propagate predictably through the DAG with clear stopping points
104+
- **Foundation for future optimizations:** This model enables possibilities like distributed compilation and build caching across CI runs
105+
106+
**The trade-off:** This approach limits some whole-program optimizations, but the gains in predictability and speed are substantial. More importantly, this clean, constrained model is exactly what makes ReWatch's sophisticated optimizations possible. The CMI hash checking, wave-based compilation, and early termination strategies all build on these fundamental properties.
107+
108+
### Understanding CMI Files
109+
110+
Now that we understand ReScript's compilation model, let's look at a specific artifact that's central to ReWatch's optimizations: the CMI file.
111+
112+
**CMI stands for Compiled Module Interface.** As mentioned, when the compiler processes your ReScript code, it generates several output files:
92113

93114
```
94115
Button.res (your source code)

0 commit comments

Comments
 (0)