Skip to content

Consider WIT extension to avoid superfluous names when defining custom component imports/exports #598

Open

Description

@lukewagner

(This isn't pressing, but I thought it would be good to have an open issue to capture this use case which was previously buried in #313 since I saw it come up again recently.)

WIT provides good support for defining worlds that are meant to be reused by many component authors by including both a namespace (to keep separate organizations from clashing) and a package name (to group related functionality that is published as an atomic unit with a version) as part of all interface and world names. However, if I'm just defining my own custom component which includes one or more custom imports or exports (not defined elsewhere), then WIT forces me to invent a namespace, package and world name that don't ultimately appear in the compiled component and are thus entirely superfluous. While this feels harmless, I've noticed it weakens tutorial and introductory material by forcing the author to make up some ignorable names and then explain that they don't matter.

For example, in:

package my:test;
world component {
  import wasi:http/client;
  export frob: func(in: string) -> string;
}

the namespace my, package name test and world name component won't show up in the .wasm of a component compiled to target my:test/component, so ideally none of them would be forced to appear in the WIT.

One possible solution is to allow worlds to be unnamed, in which case a package statement is not required or even allowed to be present:

world {
  import wasi:http/client;
  export frob: func(in: string) -> string;
}

Then this WIT could be fed into wit-bindgen or another build tool, which would know to use this unnamed world (instead of requiring the target world name to be explicitly specified).

As a purely-syntactic tweak to the above, we could address the other big, repeated bit of feedback that I've gotten which is: "What's a world? Why don't you just call it a component? That's what I was expecting and then you won't have to explain what a world is.". Now, I think component is confusing when talking about a packaged, published contracts between N hosts and M components -- in these scenarios "world" seems better than "component" IMO. But when we're talking about these non-published one-component worlds, instead of saying "worlds can be unnamed, in which case special rules apply", we could write:

component {
  import wasi:http/client;
  export frob: func(in: string) -> string;
}

and the rule is: "your WIT can contain a component definition xor a package definition", not both, which lines up with what you're actually trying to do (build a component vs. build a WIT package). I'm biased of course, but that WIT looks pretty nice and ideal for providing a gentle introduction to WIT.

Activity

  1. yordis commented on Jan 15, 2026

    @yordis
    Contributor

    I still think it’s too early, from the spec perspective.

    Even though the extra naming is mildly annoying, these definitions often grow into platform artifacts that are published, versioned, or referenced by tooling like schema registries or OTEL.

    In that context, having explicit, intentional names from the start is still valuable.

    Removing it means those tools needs to be adjusted, or people will run into "It Depends" all over the place and the WIT isn't self sufficient for things.

  2. eqrion commented on Jan 16, 2026

    @eqrion
    Collaborator

    I think something like this could be really nice. My use case is trying to create a custom component for embedding in a web application primarily written in JS. I'm not going to publish the wit anywhere, it's just needed to guide bindings generation. See here for what I ended up with.

    I had to invent three different names, 'local' 'module' and 'wasm-tools' that aren't important. It's a real conceptual speed bump when learning all of this.

  3. tschneidereit commented on Jan 16, 2026

    @tschneidereit
    Member

    I like this as well, in particular in the component {} version. One observation that seems important to me wrt @yordis' concerns is that a .wit file used to author a component can't really ever be used directly in the other direction, when trying to use the resulting component: for that case, the imports and exports have to be flipped.

    In my experience, this flipping is consistently hard to explain to people, and I think a mental model of "you define a component {}, but target a world {}, and here's how you transform one into the other" would make communicating concepts much easier.

  4. yoshuawuyts commented on Jan 16, 2026

    @yoshuawuyts
    Member

    It took a second for me to have this click, but I love this actually. The way I'm thinking about this is that we're explicitly creating paths for two separate experiences:

    • package + world: work best when you're writing a reusable interface that is meant to be published and implemented separately. For example: all of the WASI interfaces, browser.wit, and custom platform-specific WITs.
    • component: works best when you are writing program code which just wants to define sets of imports and exports. For example: the WIT interfaces in get-weather.js, time-server.js, and filesystem.rs all only exist to satisfy the imports and exports of the program.

    Reusable, versioned, and highly structured interfaces are a really helpful tool in our toolbox to have. But when we’re just writing code a lot of that structure doesn’t actually buy us much. Which you can clearly see in wassette/examples, where the values for package and world are inconsistent and clearly only exist to “make the thing work”.

  5. syntactically commented on Jan 17, 2026

    @syntactically

    I really like this as well!

    In my experience, this flipping is consistently hard to explain to people, and I think a mental model of "you define a component {}, but target a world {}, and here's how you transform one into the other" would make communicating concepts much easier.

    However, I'm not sure I completely see what you are thinking here.

  6. ricochet commented on Jan 27, 2026

    @ricochet
    Contributor

    Definitely nice to have. Letting beginners skip past worlds in their first hello world (pun intended) matches how most tutorials already handwave package names anyway.

  7. yoshuawuyts commented on Apr 27, 2026

    @yoshuawuyts
    Member

    I've been working on component tooling for the past few weeks, and another point in favor of this proposal is as a way to mitigate namespace drift. Take for example the get-weather.js component. It is published on Github Packages as microsoft/get-weather-js. We would assume the package import string would be package microsoft:get-weather-js. But in the WIT doc it's declared as package mossaka:mcp.

    When we want to render the docs on the component, this throws us for a loop. The WIT world we've defined is unique to the component and is primarily an export table. But the name we would assume the component has and the name of the world don't line up. And at least in my tooling this creates problems because we then start looking for some externally defined WIT package which doesn't exist.

    This is to say: I'm concretely running into the problem this sets out to solve. It would be very helpful if components had a native way of saying: "these are the symbols I import and export" without going through additional naming and schemes that inevitably drift when packages change owners or locations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions