Is Rescript with monorepos really this bad?

I have a yarn workspace monorepo that has the layout

apps
  - bot
  - web
packages
  - shared

Both bot and web apps have shared package listed as a pinned-dependency

bsconfig.json
{
...

  "bs-dependencies": [
    "shared"
  ],
  "pinned-dependencies": ["shared"],
}

The problem comes when I make changes to the shared package.

After every change in the shared package, I need to go through this flow to get the changes in my app code

$ yarn workspace bot add ./packages/shared       
$ yarn workspace bot rescript clean  
$ yarn workspace bot rescript build -with-deps
$ yarn workspace bot rescript build -w

Is there a better way to use yarn workspace monorepos with rescript. It was my understanding that pinned-dependencies field exests to avoid just this.

Here is the full monorepo

1 Like

Yeah, it’s how it works. I actually haven’t found value in the pinned-dependencies at all.

There are two options, you either treat shared as an actual package that should be developed separately. In this case, the solution will be to run rescript build -with-deps -w in the web and shared simultaneously.
Or instead of adding it as a dependency, you can set a path to shared in the bsconfig’s sources option. It has problems with artifact location and some other things, but it generally works.

I recommend using pnpm instead. I tried all three package managers and Pnpm workspaces wins for monorepo or single repos

2 Likes

Haven’t looked at pnpm, though have been curious.

Where would it benefit me here?

I also use pnpm and it’s good, but in this case shouldn’t be a difference

After trying lerna, yarn, and pnpm workspaces earlier this year, we have also settled on pnpm. It gets weird sometimes with it’s lock file, but a fresh pnpm install fixes it easy

The workspace feature works pretty seamlessly, if you pnpm add something it’ll just link your workspace version if you have one

I plan on introducing rescript into our monorepo soon. Do you mean you treat each package as its own package that has it’s own build step? And intellisense/module resolution is self contained right?

1 Like

Do you mean you treat each package as its own package that has it’s own build step?

Yes

1 Like

@YKW with pnpm workspaces you don’t need to do all of your work flow…
it just works as expected

We use yarn workspaces with pinned-dependencies, and it works well. The issue I see in the original post is that it needs a top-level app.

We also build multiple services (apps), so we have an empty top-level app. Using the original example:

.
├── bsconfig.json
├── package.json
├── apps
│   ├── bot
│   │   ├── bsconfig.json
│   │   └── package.json
│   └── web
│       ├── bsconfig.json
│       └── package.json
└── packages
    └── shared
        ├── bsconfig.json
        └── package.json

The top-level bsconfig.json would look something like this:

{
  ...
  "bs-dependencies": ["web", "bot", "shared"],
  "pinned-dependencies": ["web", "bot", "shared"],
}

If you make a change in shared, running yarn build at the root should build your packages as expected.

Note that you can not use yarn build -w for this blank top-level app. Quoting from the docs at https://rescript-lang.org/docs/manual/latest/build-pinned-dependencies:

ReScript will not rebuild any pinned-dependencies in watch mode! This is due to the complexity of file watching, so you’d need to set up your own file-watcher process that runs rescript build on specific file changes.

I personally use watchexec.

Do you have any OSS I can look at with this setup?

Can’t get this to work, but it makes sense.

2 Likes

I’m seeing this as well, set up a minimal repo - GitHub - hellos3b/rescript-monorepo: Linking packages in rescript using a monorepo

Looks like you need to use npx rescript clean before building if any of the dependent packages change, not sure if this is a bug or I misunderstand what pinned-dependencies is meant to do

There were several call to action for monorepo users in several discussions over several years.
Still waiting.

1 Like

So, as long as you run the watcher yourself, at least yarn v1 or npm workspace support is okay now. My subjective view is that the transitive pinned deps PR made it a bit better?

At least I have a real-world and open-source example now: the rescript-mui monorepo.

Needs watchexec binary to be installed. In the future, hopefully it will be possible to just write

npm run rewatch watch .

when rewatch supports all the different bsconfig configurations. Also rewatch aims to be more efficient with rebuilds.

I will actually try to dogfood rewatch into rescript-mui now.

1 Like

Is this for watching for changes? I don’t mind the limitation there as I typically work on packages independently. What I’m running into is if package A has a dependency on package B and you change package B, package A does not pick up up on any of the changes even with pinned-dependencies and rescript build -with-deps

Sounds like this should be possible according to this documentation page: Pinned Dependencies | ReScript Language Manual, but whenever I try to run rescript build, my main app breaks and then my extension stops working. I always have to use a rescript clean and restart the extension.

There were several call to action for monorepo users in several discussions over several years.
Still waiting.

I apologize if I’m stepping on any toes here, I just started splitting a large project into manageable pieces and ran into what seemed like a bug with building. I searched the forums for “monorepo,” read through a few posts, and replied to the one that’s most similar to my case.

edit: I just actually looked into rewatch and see that it’s specific for rescript, will try to give it a try!

For the record: Yes, rewatch is for file watching rescript builds with support for npm workspaces. But actually it is a whole build system, since it replaces bsb.exe and calls the compiler (bsc.exe) directly.

@hellos3b: I am not sure if that documentation example is the way to go. Have a look at the aforementioned rescript-mui monorepo. It uses a root bsconfig and builds are started from there.

1 Like

Update: the repo now also uses rewatch for file watching.

Keep in mind that it is a pre-release version, but it works for me.

If you are curious you can install it like so:

npm i --save-dev @rolandpeelen/rewatch@dev

5 Likes

I use NX at work for a few projects. I’ll check out what the experience is like for ReScript at some point this week and report back.

Hey, just checking, what is the “state of the art” with monorepos at the moment?

I tried rewatch today by copy-pasting the structure from rescript-mui and even got it running (with yarn, not with older npm). But I got stuck when vscode plugin didn’t really stay up to date with latest state of errors. I wonder if the plugin should even work with rewatch?

Edit: It seems allowing the vscode plugin to run its own build in addition to rewatch seems to keep the errors up to date. I’ll keep testing.

1 Like

The errors should be up to date when you run rewatch. It’s not great to run two builds at the same time because it can cause inconsistencies. Make sure to run rewatch only in the project root.

@jfrolich Hmm, I’m running rewatch in the root and using the latest commit from master.

If I get an error, it is shown in vscode, but when the error is fixed, it doesn’t disappear in vscode.

In addition to this, CPU load for rewatch is constantly at 12%.

I wonder if there are some environment requirements I should be aware of? I’m using ubuntu 20.04.