百科.dev
登录
> 返回资讯列表
news_article.exe
📰

我造了个编译器 这样我就可以不再写自定义元素锅炉了

I built a compiler so I could stop writing custom element boilerplate

2026年9月7日1 次浏览来源:Dev.to 阅读原文

我建HTMLPlus Element 上下几年。 现在是v4,500+承诺, 我从来没有真正展示给任何人。 我终于这么做了。 我对定制元素感到厌倦 是个好主意 浏览器给您一个组件模型,它比您今年使用的任何框架都有效。 它不给你 是一个愉快的方式写一个。 每个组件最终都背负着同样的运费:一个呼叫,一个静态块,宣布哪些属性被观测到,一个属性到财产的转换,用手书写给任何非字符串的东西,一个挂起你风格的地方,以及——如果其他人要使用你的元素的话——一组你所保持的TypeScript定义与他们所描述的代码分开. 这些都不是组成部分。 这是...

I've been building HTMLPlus Element on and off for a few years. It's at v4 now, 500+ commits, and I've never really shown it to anyone. So this is me finally doing that. The thing I got tired of Custom elements are a good idea. The browser gives you a component model that outlives whichever framework you happen to be using this year. What it does not give you is a pleasant way to write one. Every component ends up carrying the same freight: a call, a static block declaring which properties are observed, attribute-to-property conversion written by hand for anything that isn't a string, a place to hang your styles, and — if anyone else is going to use your elements — a set of TypeScript definitions you maintain separately from the code they describe. None of that is the component. It's the tax you pay to have one. What I did instead I moved that work into a compiler. You write the class, and the build step figures out the rest. Here is a complete component: That's the whole file, . A few things happened without me writing them: The tag name came from the class name. becomes , so the name lives in one place instead of two. The styles came from sitting next to it. Same base name, picked up automatically — no import, no styles array, no template literal. Property types were resolved from the TypeScript types you already wrote. A property arrives as a number when someone sets the attribute in HTML, without a converter. And the TypeScript definitions your consumers need were generated as part of the build, from the same source, so they can't drift out of sync with the implementation. What else is in there Everything you'd reach for is a decorator in the same package, so there's nothing extra to install: properties, state, events, listeners, public methods, watchers, shadow DOM queries, slots, and context via and . There are small helpers too — , , for RTL/LTR. The output works in any framework as it is. No wrapper packages to generate and keep in step: events are emitted under the naming convention each framework expects, so React, Vue, Angular, Svelte, Solid, Qwik and others consume the same element without a shim. The runtime is about 8 KB gzipped for a typical element, and under 11 KB for the whole library. It's not theoretical I use it to build htmlplus.io, a UI kit. Those components are written exactly the way the counter above is, and the examples on that site run in Angular, React, Vue and Svelte. If you'd rather look at output than at API design, start there. Where it's the wrong tool It compiles, which means a build step. If you want to drop a tag on a page and start writing an element, or you need two components and not twenty, a runtime-only library is a better fit and I'd rather say so than have you find out later. It's a bundler plugin rather than a toolchain of its own — Vite and Rollup today, built on unplugin, so more can follow. Server-side rendering to Declarative Shadow DOM is in progress but not released. Try it Repo: https://github.com/htmlplus/element (MIT) I'd rather have criticism of the API design than stars. If something here looks wrong to you, I genuinely want to hear it.

> 分享: