|  | 
|  | 1 | +--- | 
|  | 2 | +title: "Setting up a monorepo" | 
|  | 3 | +metaTitle: "Setting up a monorepo" | 
|  | 4 | +description: "Setting up a monorepo" | 
|  | 5 | +canonical: "/docs/manual/v12.0.0/build-monorepo-setup" | 
|  | 6 | +--- | 
|  | 7 | + | 
|  | 8 | +# Setting up a monorepo with ReScript | 
|  | 9 | + | 
|  | 10 | +**Since 12.0** | 
|  | 11 | + | 
|  | 12 | +> A monorepo is a single repository containing multiple separate projects, with clear relationships between them. | 
|  | 13 | +
 | 
|  | 14 | +ReScript 12.0 introduces improved support for native monorepos through the new "Rewatch" build system. This guide walks you through the setup process. | 
|  | 15 | + | 
|  | 16 | +**Note:** This feature requires the new build system and is **not compatible** with `rescript-legacy`. | 
|  | 17 | + | 
|  | 18 | +## Project Structure | 
|  | 19 | + | 
|  | 20 | +A ReScript monorepo requires a `rescript.json` file at the repository root, plus a `rescript.json` file in each sub-project directory. | 
|  | 21 | +Basically, the monorepo contains a root package that manages all local dependencies. Building the root package will build all its dependencies. | 
|  | 22 | + | 
|  | 23 | +**Important:** You also need a node_modules monorepo setup with symlinks. In practice, if you want a ReScript monorepo, you will also need an npm/yarn/pnpm/bun monorepo. | 
|  | 24 | + | 
|  | 25 | +A typical structure looks like this: | 
|  | 26 | + | 
|  | 27 | +``` | 
|  | 28 | +my-monorepo/ | 
|  | 29 | +├── rescript.json | 
|  | 30 | +├── package.json | 
|  | 31 | +├── node_modules/ | 
|  | 32 | +│   ├── package-1/ # symlinked | 
|  | 33 | +│   ├── package-2/ # symlinked | 
|  | 34 | +├── packages/ | 
|  | 35 | +│   ├── package-1/ | 
|  | 36 | +│   │   ├── rescript.json | 
|  | 37 | +│   │   ├── package.json | 
|  | 38 | +│   │   ├── src/ | 
|  | 39 | +│   ├── package-2/ | 
|  | 40 | +│   │   ├── rescript.json | 
|  | 41 | +│   │   ├── package.json | 
|  | 42 | +│   │   ├── src/ | 
|  | 43 | +│   ├── ... | 
|  | 44 | +``` | 
|  | 45 | + | 
|  | 46 | +## Root `rescript.json` Configuration | 
|  | 47 | + | 
|  | 48 | +The root `rescript.json` manages the monorepo by listing its packages. | 
|  | 49 | + | 
|  | 50 | +```json | 
|  | 51 | +{ | 
|  | 52 | +  "name": "my-monorepo", | 
|  | 53 | +  "dependencies": ["package-1", "package-2"], | 
|  | 54 | +  "package-specs": { | 
|  | 55 | +    "module": "esmodule", | 
|  | 56 | +    "in-source": true | 
|  | 57 | +  }, | 
|  | 58 | +  "suffix": ".res.mjs", | 
|  | 59 | +  "bsc-flags": [] | 
|  | 60 | +} | 
|  | 61 | +``` | 
|  | 62 | + | 
|  | 63 | +The `"dependencies"` array lists the names of your packages, which must match the `"name"` fields in their respective sub-rescript.json files. | 
|  | 64 | +When you build a package in ReScript, it will use the `"package-specs"` and `"suffix"` settings from the root package. | 
|  | 65 | +Therefore, it is recommended to place these settings in the root `rescript.json` file and avoid specifying them in local package `rescript.json` files. | 
|  | 66 | + | 
|  | 67 | +**Settings from different config files:** When Rewatch builds a package within a monorepo setup, it uses these settings from the root rescript.json: | 
|  | 68 | + | 
|  | 69 | +- `"jsx"` (jsx_args, jsx_module_args, jsx_mode_args, jsx_preserve_args) | 
|  | 70 | +- `"experimental"` (experimental_features_args) | 
|  | 71 | +- `"package-specs"` (used for implementation_args) | 
|  | 72 | +- `"suffix"` (used for package output) | 
|  | 73 | + | 
|  | 74 | +These settings come from the package's own rescript.json: | 
|  | 75 | + | 
|  | 76 | +- `"sources"` (determines which files to compile) | 
|  | 77 | +- `"dependencies"` (package dependencies) | 
|  | 78 | +- `"warnings"` (warning_args) | 
|  | 79 | +- `"compiler-flags"` (bsc_flags) | 
|  | 80 | + | 
|  | 81 | +When the root package is built, Rewatch will look for the dependencies inside the `my-monorepo/node_modules` folder. | 
|  | 82 | +It is expected that `package-1` and `package-2` are available there via a symlink system provided by your node_modules package manager. | 
|  | 83 | + | 
|  | 84 | +Note that your root rescript.json is allowed to have a `"sources"` setting. | 
|  | 85 | +These files will be compiled as expected. | 
|  | 86 | + | 
|  | 87 | +## Package `rescript.json` Configuration | 
|  | 88 | + | 
|  | 89 | +Each nested rescript.json sets up a specific package. | 
|  | 90 | + | 
|  | 91 | +`packages/package-1/rescript.json`: | 
|  | 92 | + | 
|  | 93 | +```json | 
|  | 94 | +{ | 
|  | 95 | +  "name": "package-1", | 
|  | 96 | +  "sources": ["src"], | 
|  | 97 | +  "dependencies": [], | 
|  | 98 | +  "compiler-flags": ["-open Foobar"] | 
|  | 99 | +} | 
|  | 100 | +``` | 
|  | 101 | + | 
|  | 102 | +`packages/package-2/rescript.json`: | 
|  | 103 | + | 
|  | 104 | +```json | 
|  | 105 | +{ | 
|  | 106 | +  "name": "package-2", | 
|  | 107 | +  "sources": ["src"], | 
|  | 108 | +  "dependencies": ["package-1"], | 
|  | 109 | +  "warnings": { | 
|  | 110 | +    "number": "-27" | 
|  | 111 | +  } | 
|  | 112 | +} | 
|  | 113 | +``` | 
|  | 114 | + | 
|  | 115 | +In `package-1`, we show how to use special compiler flags. | 
|  | 116 | +In `package-2`, we show how to disable warning 27 (unused variable). | 
|  | 117 | +In both cases, the settings only apply to the package where they are specified. | 
|  | 118 | +Defining these in the root rescript.json will not affect the packages. | 
|  | 119 | +There is no inheritance system. | 
|  | 120 | + | 
|  | 121 | +Also note the dependencies array in `package-2`, which allows that package to depend on `package-1` within the monorepo. | 
|  | 122 | + | 
|  | 123 | +## Building the monorepo | 
|  | 124 | + | 
|  | 125 | +From the root directory, you can run all ReScript commands: | 
|  | 126 | + | 
|  | 127 | +```bash | 
|  | 128 | +# Build all packages | 
|  | 129 | +rescript build | 
|  | 130 | + | 
|  | 131 | +# Clean all packages | 
|  | 132 | +rescript clean | 
|  | 133 | + | 
|  | 134 | +# Format all packages | 
|  | 135 | +rescript format | 
|  | 136 | +``` | 
|  | 137 | + | 
|  | 138 | +### Building individual packages | 
|  | 139 | + | 
|  | 140 | +You can also run ReScript commands on individual packages instead of the entire monorepo. This is useful when you only want to work on one package. | 
|  | 141 | + | 
|  | 142 | +```bash | 
|  | 143 | +# Build from the package directory | 
|  | 144 | +cd packages/package-3 | 
|  | 145 | +rescript build | 
|  | 146 | +rescript clean | 
|  | 147 | +rescript format | 
|  | 148 | + | 
|  | 149 | +# Or run from the root directory | 
|  | 150 | +rescript build packages/package-3 | 
|  | 151 | +rescript clean packages/package-3 | 
|  | 152 | +rescript format packages/package-3 | 
|  | 153 | +``` | 
|  | 154 | + | 
|  | 155 | +When building a single package, ReScript will use the settings from the root rescript.json as explained in the [Root rescript.json Configuration](#root-rescriptjson-configuration) section above. | 
|  | 156 | + | 
|  | 157 | +### Building without a root rescript.json | 
|  | 158 | + | 
|  | 159 | +If your node_modules monorepo is set up with symlinks, you can build packages even without a root rescript.json: | 
|  | 160 | + | 
|  | 161 | +``` | 
|  | 162 | +my-monorepo/ | 
|  | 163 | +├──node_modules/ | 
|  | 164 | +│   ├── package-1/ # symlinked | 
|  | 165 | +│   ├── package-2/ # symlinked | 
|  | 166 | +├── package.json | 
|  | 167 | +├── packages/ | 
|  | 168 | +│   ├── package-1/ | 
|  | 169 | +│   │   ├── rescript.json | 
|  | 170 | +│   │   ├── package.json | 
|  | 171 | +│   │   ├── src/ | 
|  | 172 | +│   ├── package-2/ | 
|  | 173 | +│   │   ├── rescript.json | 
|  | 174 | +│   │   ├── package.json | 
|  | 175 | +│   │   ├── src/ | 
|  | 176 | +│   ├── ... | 
|  | 177 | +``` | 
|  | 178 | + | 
|  | 179 | +Building `package-2` (which depends on `package-1`) will search up the folder structure to find `package-1`. | 
|  | 180 | + | 
|  | 181 | +Example: | 
|  | 182 | + | 
|  | 183 | +```bash | 
|  | 184 | +rescript build ./packages/package-2 | 
|  | 185 | +``` | 
|  | 186 | + | 
|  | 187 | +Internally, Rewatch will look for: | 
|  | 188 | + | 
|  | 189 | +- 🔴 `my-monorepo/packages/package-2/node_modules/package-1` | 
|  | 190 | +- 🔴 `my-monorepo/packages/node_modules/package-1` | 
|  | 191 | +- ✅ `my-monorepo/node_modules/package-1` | 
|  | 192 | + | 
|  | 193 | +This only happens as a last resort if `package-1` is not listed as a (dev-)dependency in a parent `rescript.json`. | 
|  | 194 | + | 
|  | 195 | +## Troubleshooting | 
|  | 196 | + | 
|  | 197 | +If you're having issues with your monorepo setup, you can use the `-v` flag during build to see what Rewatch detected as the project context: | 
|  | 198 | + | 
|  | 199 | +```bash | 
|  | 200 | +rescript build -v | 
|  | 201 | +``` | 
|  | 202 | + | 
|  | 203 | +This will show you detailed information about how Rewatch is interpreting your project structure and which configuration files it's using. | 
|  | 204 | + | 
|  | 205 | +## Recommendation | 
|  | 206 | + | 
|  | 207 | +**The ReScript team strongly recommends using a root `rescript.json` file when setting up monorepos.** While it's technically possible to build packages without one (as shown in the section above), having a root configuration file provides several benefits: | 
|  | 208 | + | 
|  | 209 | +- **Consistent settings** across all packages (jsx, experimental features, package-specs, suffix) | 
|  | 210 | +- **Simplified dependency management** through the root dependencies array | 
|  | 211 | +- **Better developer experience** with unified build commands from the root | 
|  | 212 | +- **Easier maintenance** and configuration updates across the entire monorepo | 
|  | 213 | + | 
|  | 214 | +The root `rescript.json` approach is the intended and supported way to work with ReScript monorepos. | 
0 commit comments