Wraplet vs Web Components | Wraplet
Skip to main content<br>Introduction
Wraplet and Web Components aren't strangers. They share a lot of DNA, and the<br>best way to see it is to look at the same widget written in both.
Here is a simple "color toggle" as a Web Component:
The Web Components clicker
The Wraplet clicker
Look at them side by side and you'll notice they aren't that different:
A class per element. Behavior lives in a class, not in a hook tree, a<br>template, or a reactivity graph. What you see in the file is what runs in<br>the browser.
No virtual DOM. Neither one diffs anything or rewrites<br>your source (well, except the TypeScript transpiler). The class touches the real DOM,<br>with the real DOM APIs.
Lifecycle hooks. Both expose a "this is where I start working" hook<br>and a "this is where I tear down" hook. Custom elements call them<br>connectedCallback and disconnectedCallback; wraplets call them<br>onInitialize and onDestroy.
Framework-agnostic. A Web Component lives in any page that can render<br>its tag. A wraplet lives in any page that can run its script. Both play<br>nicely with React, Vue, Angular, plain HTML, or any server-rendered<br>template.
At home in server-rendered HTML. Neither asks you to rebuild your<br>pages as a single-page app. They just add behavior to markup that already<br>exists.
If your mental model of frontend code is "DOM nodes with classes on them,<br>not a render tree," both technologies will feel familiar.
So where's the actual difference?
The similarities run out the moment you ask: what is a component?
A custom element is an HTMLElement subclass. The class and the element<br>are the same object – document.querySelector("color-toggle") returns the<br>instance itself. A wraplet, by contrast, wraps a node. The class lives<br>in this, the node lives in this.node, and the two are bound together but<br>remain separate. The HTML stays whatever it already was – a , a<br>, an – and behavior is attached to it by selector.
This single decision shapes everything that follows: composition,<br>lifecycle, and dependency management all flow from it. We'll come back to<br>those in the next section.
Lifecycle comparison
Web Component's lifecycle is the same as the element's lifecycle.
Wraplet's lifecycle is decoupled from the element's one. Wraplet can be initialized<br>before the element is added to the DOM or destroyed before it is removed.
Additionally, wraplet's lifecycle events can be chained together by the DependencyManager<br>making it possible to treat multiple interdependent wraplets, managing their own dependencies, as a single unit.
Dependency management, side by side
Wraplet's dependency management is declarative. To see what that means in<br>practice, compare the same "greeter" widget written both ways. First, the<br>Web Component:
The compiler has no way to verify that [data-name] actually matches an<br>, or that the markup was rendered at all. Rename a selector in the<br>HTML and nothing in the TypeScript complains – until a user clicks the button.
Now the same widget as a wraplet:
The dependency map declares each child<br>once: a selector, a class, and a few flags. From that single source,<br>TypeScript infers everything else. this.d.nameInput is a NameInput<br>instance with its own methods, not an HTMLInputElement you had to cast.<br>Rename a key and every usage breaks loudly, in the compiler, before the<br>page ever loads. Mis-type a child's API and you fail to compile.
Web Components have no equivalent. Slots help with placement, not with<br>typing. You can build a typed wrapper layer on top, but then you're<br>recreating, by hand, what Wraplet gives you out of the box.
Side note : You may have noticed that the Wraplet example is more verbose.<br>The additional code is not a dead weight, though, so don't be discouraged by it.<br>The dependency map and the contracts exposed by dependencies make code much more readable.<br>Wraplet is all about what's great in OOP: encapsulation and contracts. If you follow the<br>recommended practices, it will always be trivial to understand the component's structure.It's not strictly forced, though. You are free to implement impure wraplets.<br>These are the wraplets that reach out and interact with multiple nodes directly.<br>You'll lose the clarity of dependency structure and contracts but reduce the code verbosity<br>to the Web Component's level, while keeping some of the other wraplet's advantages. Like the<br>ability of an impure wraplet to participate in a dependency tree of another wraplet or<br>automatic listener cleanup.Ignoring the feature of dependency map is not recommended, though, because readability is difficult<br>to overestimate, and wraplet is all about readability and long-term maintainability.You can think about Wraplet's verbosity this way: It's not a flashy Ferrari supposed to<br>get out of fashion next week. It's a military truck of JavaScript frameworks. Made to be easy to<br>maintain and reliable, first and foremost.
Listener cleanup
In a Web Component, every listener you attached in connectedCallback...