Shared WIT packages
When having multiple components in an application, we often want to share some of the WIT types between them. The application template used by golem app new
contains a predefined way to add these shared packages.
Create a new package
The application's root directory has a wit
directory, initially only containing an empty common.wit
file. This file is just there to satisfy the requirements of some build tools, such as wit-bindgen
. It should not be modified.
Instead, create a new package in a subdirectory of wit/deps
, for example wit/deps/shared/shared.wit
. Each subdirectory of wit/deps
must contain one particular package, but these packages can consist of multiple WIT files.
For example the shared.wit
file can define an interface with a few data types:
package myapp:shared;
interface types {
type name = string;
record user {
id: u64;
name: name;
}
}
Importing the shared package
To import this shared package into one or more of the component's WIT files, just add an import
statement to the component's world like in the following example:
package myapp:component1;
// ...
world component1 {
import myapp:shared/types;
// ...
}
and use the use
statement to import members of the shared interface into another one:
interface api {
use myapp:shared/types.{name, user};
// ...
}
There is no other steps required - golem app build
will automatically find the shared package and wire everything together as expected.
Sharing code between components depending on shared WIT packages
The application templates contain predefined "shared" libraries for most supported languages which can be used to shared code between components.
These are located in the common-*
directories, where *
is the language. For example, the common-rust
directory contains additional Rust crate that can be added as dependencies to the component implementations.
When using shared WIT packages like above, it makes sense to write shared code depending on the bindings generated from these shared WIT packages. For example, there could be a JSON codec implemented for the above defined user
record type which we want to use in multiple components.
Doing so requires setting up a custom binding generation step, which depends on the language being used:
First add the wit-bindgen
crate as a dependency to your shared crate under the common-rust
directory:
[dependencies]
wit-bindgen = "0.37.0"
Then use the binding generator macro pointing to the shared WIT package, for example:
use wit_bindgen::generate;
generate!({
path: "../../wit",
inline: r#"
package common:inline;
world common {
import myapp:shared/types;
}
"#,
// additional_derives: [serde::Deserialize, serde::Serialize],
generate_all,
generate_unused_types: true
});
use crate::myapp::shared::types::*;