title | metaTitle | description | canonical |
---|---|---|---|
Pinned Dependencies |
Pinned Dependencies |
Handling multiple packages within one ReScript project with pinned dependencies |
/docs/manual/latest/build-pinned-dependencies |
Usually we'd recommend to use ReScript in a single-codebase style by using one rescript.json
file for your whole codebase.
There are scenarios where you still want to connect and build multiple independent ReScript packages for one main project though (npm
workspaces-like "monorepos"). This is where pinned-dependencies
come into play.
Before we go into detail, let's first explain all the different package types recognized by the build system:
- Toplevel (this is usually the final app you are building, which has dependencies to other packages)
- Pinned dependencies (these are your local packages that should always rebuild when you build your toplevel, those should be listed in
bs-dependencies
andpinned-dependencies
) - Normal dependencies (these are packages that are consumed from npm and listed via
bs-dependencies
)
Whenever a package is being built (rescript build
), the build system will build the toplevel package with its pinned-dependencies. So any changes made in a pinned dependency will automatically be reflected in the final app.
The build system respects the following rules for each package type:
Toplevel
- Warnings reported
- Warn-error respected
- Builds dev dependencies
- Builds pinned dependencies
- Runs custom rules
- Package-specs like JavaScript module or CommonJS overrides all its dependencies
Pinned dependencies
- Warnings reported
- Warn-error respected
- Ignores pinned dependencies
- Builds dev dependencies
- Runs custom rules
Normal dependencies
- Warnings, warn-error ignored
- Ignores dev directories
- Ignores pinned dependencies
- Ignores custom generator rules
So with that knowledge in mind, let's dive into some more concrete examples to see our pinned dependencies in action.
Let's assume we have a codebase like this:
myproject/
app/
- src/App.res
- rescript.json
common/
- src/Header.res
- rescript.json
myplugin/
- src/MyPlugin.res
- rescript.json
package.json
Our package.json
file within our codebase root would look like this:
{
"name": "myproject",
"private": true,
"workspaces": {
"packages": [
"app",
"common",
"myplugin"
]
}
}
Our app
folder would be our toplevel package, consuming our common
and myplugin
packages as pinned-dependencies
. The configuration for app/rescript.json
looks like this:
{
"name": "app",
"version": "1.0.0",
"sources": {
"dir" : "src",
"subdirs" : true
},
/* ... */
"bs-dependencies": [
"common",
"myplugin"
],
"pinned-dependencies": ["common", "myplugin"],
/* ... */
}
Now, whenever we are running rescript build
within our app
package, the compiler would always rebuild any changes within its pinned dependencies as well.
Important: 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.