Pinned Dependencies project structure

Working on an Electron app and trying to get the various bsconfig.json files working. For context: Electron has three completely separate scripts that run that define a running app: a “main” process that runs a node app, a “renderer” process that runs in a browser window, and a “preload” script that binds the two together. Most people who are used to something like TypeScript just treat these as three separate projects (they don’t directly depend on one another).

For ReScript, that seems to imply using the pinned dependencies feature to allow specifying that the renderer process depends on the main process to build. That’s not strictly true since the renderer process cannot actually call code from within the “main” process, but the “app” itself is really a function of all three of these parts.

Looking at the docs, I see an example of what the app/bsconfig.json should look like, but no examples of the other config files. Also, if I do not have a /bsconfig.json in my project it seems to fail when running npx rescript build complaining that I’m missing that “top-level” bsconfig.json even though the documentation doesn’t mention it at all. Can someone point me to maybe a repo of a working example or help me to flesh out how best to tackle this using pinned dependencies?

I’m also open to suggestions that I should not use pinned dependencies here and maybe there is a way to treat each sub-project as a proper “ReScript” project with no direct dependencies, that’s really all I need, but can’t figure out how to configure the rescript CLI to understand the various subdirectories: it always keeps suggesting that I’m missing a bsconfig.json in the shared “root”. Not sure how it determines where that location is.

1 Like

So electron works like a monorepo?
I work in a monorepo using pnpm workspaces.

I have my apps in apps/* and I put the Rescript shared lib in packages/shared
Each app and the shared lib have their own bsconfigs. But the Apps use pinned-dependencies to use the shared lib.

It’s similar to a monorepo, but it’s the two “packages” do not actually share any code. Electron runs two separate processes: one Node process (called “main”) and one Chromium process (called “renderer”). Since they don’t really share any code, it’s kind of weird to make them dependent on each other, but that’s certainly one way to think about them.

Roughly, I’m just trying to figure out how to get multiple bsconfig.json files to be treated as distinct ReScript projects. What I’m trying to do conceptually is:

/package.json
/vite.config.js
/main/bsconfig.json
/renderer/bsconfig.json

But running npx rescript build in either sub directory seems to try to run it in the base directory instead of in the “package” directories, but I can’t figure out how the rescript CLI figures what the “base” path is.

The workaround that I’m currently do is just making the “renderer” the main app and namespacing “main”. It works but doesn’t allow me to treat each part as separate so I end up with a ton of Main__Foo and Main__Bar modules to avoid conflicting with some matching Foo and Bar module in the renderer.

IMO it’s not worth the hazzle trying to separate the different parts of your app by introducing different compile units.

Just use a single bsconfig.json for the whole app and work in your project as you’d do in JS.

Here’s an example app I built back then:

2 Likes

Thanks for this example repo, it was extremely useful in my switch to Webpack! For anyone coming here who is also trying out Vite and Electron, I’d recommend against it for now. The electron module system is pretty whacky given that it is CommonJS in the main process and ES modules in the renderer process.

I’d still love a solution that integrated the ReScript compiler with the Webpack process so I don’t need to run two terminals during dev, and once I get that running, I’ll throw together an updated boilerplate repo for Electron+ReScript+Webpack+Tailwind. It’s just finicky enough to want some guidance if you’re picking it up for the first time.

I’ve been using npm-run-all for this for many years. The only downside is that it mixes up the output which sometimes means you have to scroll up for an error. I haven’t found anything that automatically splits the terminal in boxes based on the number of processes.

I also use npm-run-all, it’s a little bit easier to navigate if you add the --print-label flag.

2 Likes