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?

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.

1 Like