Thanks for your response! I ended up figuring that out shortly after I sent the message here... lol
I published with warg
instead of wkg
. I wonder if these are equivalent?
I indeed published the built component rather than just the package/"interface".
It does makes sense to me now that the component wraps it in a new package/world, but initially I was confused on the difference -- specially because they are both .wasm
I think.
I have been working on migrating my application from wasm core modules + protobuf to just wasm components. I really like the design of components (even if all the tools are a bit overwhelming to understand at first lol) -- so many great use cases for this. I wish I had looked more into components before I went the protobuf route a few months ago haha
Lorenzo has marked this topic as resolved.
I don't think it has to be a one or the other! They work great together :)
IMO WIT is a higher level than protobuf, because it does not specify things like binary encoding, so it's the more general tool. There's no reason you can't use them together!
If you run into any documentation that would have helped you figure this out faster, please feel free to point it out (or even update/send a PR if you have the time!)
Yeah I agree re protobuf & WIT. I replaced protobuf in my case because the only reason I was using it was for serializing data from/to wasm, but WIT already does that, plus wasm-to-wasm calls so there's no reason for me to keep protobuf I don't think.
I'll definitely try to help contribute to docs as much as I can. I opened a PR into the component-docs repo making some adjustments to the Go example :)
@Victor Adossi I'd like you to elaborate on "While you can use it however you'd want, I like to think of the ability to push a component to a registry to be for types-only components -- not components that are fully built with functionality as well (though of course the tooling will work with both." While that would be an OBVIOUS reason to push a component, I would think there would be several different implementations of wasi:sql or wasi:messaging, for example, that would be pushed in order to use.
Are you thinking about it differently?
Well in my case I actually require both the WIT and the component binary. So naturally I thought I could publish only the binary, and users that need only the WIT (for generating type bindings for example) can use tooling to extract just that, but the tooling doesn't seem to work this way -- where you can usetypes.wit
or types.wasm
you can't use component.wasm
, it doesn't work, for example wkg wit build
or wkg wit fetch
will fail. I think it's possible to make it work though, and would make things much more intuitive.
Let me explain further:
1 - from the perspective of a user/developer writing a component, you start by writing your .wit
which may import dependencies and then you generate typings for those dependencies in your preferred language, then you can start implementing the component. To generate these typings, you need the .wit
s
2 - from the perspective of building & running a component, the wasm component binary of all dependencies are required so that it can be composed (or alternatively linked at runtime by the host implementation -- which is what I'm doing)
Publishing a single package as a component (rather than two packages, component + WIT) would serve both of these points.
My confusion here comes from my first attempt to publish a component, then to consume it as a dependency by doingwkg wit build
but that failed and I wasn't able to generate go typings from the published component.wasm
.
I had to publish only the wit
for wkg wit build
to work from the dependent project. I am able to generate go typings by running:
# published & depends on a WIT package (not component.wasm)
wkg wit build
# WIT package written to example:component.wasm
wit-bindgen-go generate example:component.wasm
# successfully generated types
So basically I'm trying to find out if there a way to extract the equivalent of the file outputted by wkg wit build
from a component.wasm
? Because I'm not able to generate typings (nor run wkg wit build
itself) if my package points to a component.wasm
dependency rather than a WIT. I suspect because there is some renaming of namespaces when you build a component, namely the package becomes root:component
-- so it's no longer equivalent to the WIT package.
To me it seems like a component.wasm
should be fully interchangeable with its WIT package but that doesn't seem to be the case currently across the tooling. I think it would make things much more intuitive for users if that were the case, and to me it seems possible and just a matter of updating the metadata or perhaps adding a new keyword to WIT
to resolve it.
Curious if anyone has any thoughts on this.
Ralph said:
Victor Adossi I'd like you to elaborate on "While you can use it however you'd want, I like to think of the ability to push a component to a registry to be for types-only components -- not components that are fully built with functionality as well (though of course the tooling will work with both." While that would be an OBVIOUS reason to push a component, I would think there would be several different implementations of wasi:sql or wasi:messaging, for example, that would be pushed in order to use.
Ah I think this might be a misunderstanding -- I mean that specifically for @Lorenzo 's use case. It's not that you shouldn't push functionality to a registry, it's that you shouldn't wkg wit publish
a "functional" (i.e. composed/non-composed/optimized) component if you intend to use it "for" types.
There's a sort of implicit difference between components that hold functionality and ones that exist to mostly hold WIT.
Agree that there should and will be different implementations of wasi:*
or any-ns:any-package
now and in the future, but when you want to pull the actual interface (for example with wkg wit fetch
you're going to want to pull the WIT-only version to to build your project against). Once you want to actually compose functionality in, then you need the versions with the functionality (which have to agree on the likely types-only WIT contract).
Trying to use the "implementation" component for everything leads to a very interesting versioning problem -- given company:msg-impl@0.2.0
, which version of wasi:messaging
does it use? Moving between versions could introduce type changes from the underlying contract (that just happens to be used in company:msg-impl
(of course you'd run into the problem Lorenzo ran into first, before you even had that problem).
So that's why for me it seems like there's an important difference here between WASMs that just hold WITs and WASMs that hold WIT and functionality.
@Lorenzo Regarding your post afterwards -- we're certainly open to issues and PRs! Maybe it should work that way (maybe it should be easier to "extract" WIT from functional WASMs for use when pulling a dep) -- the information is already there after all, it's just renamed due to the build/composition process.
Agreed that publishing as a single package would definitely be more convenient, but see the versioning issue I mentioned above -- schemas and implementations should likely be kept intentionally separate, IMO. Definitely open to thinking of a work flow that could make this intuitively work though.
Note that component.wasm
has the same exact information as wkg wit build
, the problem is that the output world is just renamed because there is one root world (last paragraph there). This possibly could be changed, but definitely some discussion on this discontinuity is worth discussing!
IMO making an issue (on the component model repo??) would be a great place to start and get discussion going
Thanks @Victor Adossi! I'll look into opening an issue for this :)
I understand the versioning issues you mentioned.
The approach I am going to use with my application is to, for each component, publish every WIT & component impl under 2 different namespaces, for example company:msg
for the WIT and company-component:msg
for the implementation -- so the company-component
namespace holds implementations and company
holds WITs. I wonder if this is a common pattern used by people.
If the versioning issue can be resolved in a simple & elegant way, then for use cases such as mine only the implementation could be published to the registry (inherently containing the WIT as well). It would be even better if wkg wit build
& other commands that only need WIT could then download only the WIT information, to not waste bandwidth on the implementation.
Lorenzo said:
Thanks Victor Adossi! I'll look into opening an issue for this :)
I understand the versioning issues you mentioned.
The approach I am going to use with my application is to, for each component, publish every WIT & component impl under 2 different namespaces, for example
company:msg
for the WIT andcompany-component:msg
for the implementation -- so thecompany-component
namespace holds implementations andcompany
holds WITs. I wonder if this is a common pattern used by people.
Yep this seems fine -- I'm wondering if you could have company:package
and company:components-<name-of-component
or something like that might make more sense, if components have well defined names.
I think it's kind of awkward to try to represent implementations of WIT interfaces behind the namespace/package mechanism -- it kind of wasn't meant for that. wkg
has evolved support for OCI registries because storing runnable artifacts is a much better fit for an OCI registry (where the "namespace" is your.registry.io/whatever/org/structure/you/want/component:0.1.0
)
At Cosmonic (we build wasmCloud) at least, we push both our WITs and our runnable components to OCI registries and are happy with that setup. When it's time to wkg wit fetch
we can do that (and we fetch the types-only component), and when it's time to publish something runnable we publish (and @ runtime we refer to the OCI address).
Lorenzo said:
If the versioning issue can be resolved in a simple & elegant way, then for use cases such as mine only the implementation could be published to the registry (inherently containing the WIT as well). It would be even better if
wkg wit build
& other commands that only need WIT could then download only the WIT information, to not waste bandwidth on the implementation.
I think this could definitely work -- a few new flags on wkg wit publish
(ex. --wit-only
) could probably make this happen.
Speaking of which, did you try wkg publish --package <your package name>
? I'm probably a bit late in asking, but usually when you wkg publish
a WASM file, you can choose which package you want to send along., and actually wkg
will only send *that* package.
You can see in that code the delineation between a component and a WIT package (which I've been calling a "types only component")
Last updated: Feb 28 2025 at 03:10 UTC