Nice work! I'm also a fan of the runtime only frameworks. They might not be as efficient as the compiled counterparts on paper, but in my experience the performance loss is almost negligible compared to the rest of the stack.
Thanks! Totally agree — in most real-world apps the “runtime overhead” ends up dwarfed by everything else in the stack, so the build-free ergonomics can be a bigger win.
And nice, Mancha looks cool — I’ll give it a read and star. It looks similar with dagger in some features, for instance, mancha uses :data to create scope while dagger uses +load directive. Always great to see other takes on the runtime/compile spectrum; I think having multiple approaches out there is healthy for the ecosystem!
I’d actually love to see something that goes in the opposite direction, highly optimized and compiled, where the result is as small, fast, and efficient as possible. I get that a lot of people dislike compilation, but once I have the CI set upI never found build steps to be a problem for me.
Some time ago while I was experimenting with writing Debian benchmarks[0], I found that by completely avoiding strings, using Uint8Arrays, and manually managing bounds/memory, I could squeeze out performance that almost made you forget you were writing JavaScript. I never ended up submitting a PR, but it was pretty eye-opening.
At one point I went into a rabbit hole and tried to build something similar on my own, but it got complicated very quickly given my limited compiler knowledge. That’s why I always thought Prepack[1] was such a cool idea.
Thanks for your comment.That's right — the compiled/optimized end of the spectrum is powerful, and I think Prepack showed just how far you can push that. However, dagger.js is intentionally the opposite: it trades the simplest usage for zero build, instant setup. My focus is “drop in a <script> and go,” not competing with compiler-driven stacks. In practice I see them as complementary — one for squeezing every byte/cycle, the other for minimizing friction and complexity.
Isn't that what Svelte was aiming to do? It's moved on a ways since then, but you can still see the fundamentals in its demos: https://svelte.dev/playground/hello-world
That’s a good comparison — Svelte also started from the “write less, ship less” idea, and I have a lot of respect for it.
The big difference is that Svelte achieves that by compiling away the framework, whereas Dagger.js avoids compilation entirely. You don’t install a CLI, you don’t run a build — you literally drop a <script> from a CDN and wire up directives in plain HTML. It’s closer to Alpine/htmx in that sense, but with a focus on working alongside Web Components.
So in spirit, yes — both try to reduce overhead. Svelte optimizes post-build output; Dagger.js tries to remove the build step altogether.
> I’d actually love to see something that goes in the opposite direction, highly optimized and compiled, where the result is as small, fast, and efficient as possible
Right, but that is what basically every JS framework is going for these days. Its refreshing to see somebody trying to go back to old school non-compiled js/html where every front-end is open-source(ish)
Really appreciate that. The “old school” vibe is deliberate — I wanted to lower the barrier so that you can share a snippet or inspect a page and actually learn from it, the way we used to with plain HTML/JS. Frameworks are great, but sometimes it’s nice to have a path that prioritizes openness and simplicity over machinery.
I’m in a similar boat like you. I would love for a React-like library that compiles down to direct JavaScript DOM transforms. Of course Svelte exists but I don’t want to mark what is reactive or not and I can’t go back to html templates after using typed JSX. Also I don’t really like the “island” like template syntax of Vue, Svelte, etc
Thanks for your comment. — typed JSX ergonomics are really nice, and most compile-time frameworks today make you choose between that and some sort of template DSL.
However, dagger.js takes a different angle: it doesn’t try to be “React-like compiled,” it tries to be no-compile at all. State is just plain JS, DOM transforms happen directly via attributes (+click, +load, etc.), and everything is HTML you can literally view-source.
So it’s not competing with React/Svelte on compile sophistication — it’s aiming to be the lightweight “glue” around whatever components you like, while keeping the HTML open and approachable.
I really hope you will try using dagger.js and come back to tell me how you feel about it.
Thanks!
Solid is definitely in that “compile-to-direct-DOM” camp, and I think it’s awesome — it shows how far you can push the reactive model with JSX + fine-grained updates.
dagger.js is coming from the opposite direction: no compiler, no JSX, and also no signals. just plain HTML with attributes like +click / +load. You drop in a <script> from a CDN and it wires up behavior at runtime. It’s more about zero build friction and “view-source-ability”than squeezing out maximum perf.
So if Solid is about compiling React-like ergonomics down to efficient DOM transforms, dagger is about skipping compilation entirely and letting you glue components together with HTML. Two very different trade-offs, but complementary ends of the spectrum.
I also meant more advanced optimizations beyond what svelte does, like: inlining, loop unrolling, partial evaluation that would trickle down to the frameworks as well. I am aware that some of these and others are very hard to do on javascript as prepack shows.
Yeah, totally — once you start talking about inlining, loop unrolling, partial evaluation, you’re basically in compiler-research territory. Prepack showed both the promise and the difficulty of doing that well in JavaScript.
dagger.js isn’t trying to chase those kinds of deep compile-time optimizations. Its focus is the opposite trade-off: keep things build-free, HTML-first, and easy to drop into a page. I’d rather leave the heavy lifting to whatever compiler or bundler someone pairs it with, and make sure the runtime layer stays simple and transparent.
So in my mind these approaches complement each other: advanced compilers make large apps faster; Dagger tries to make small apps and prototypes friction-less.
Right — there’s also the dagger DI framework in the Java ecosystem. To avoid confusion: this project is dagger.js, a small runtime-only JavaScript library for HTML/Web Components. Totally unrelated to the Java DI framework other than sharing the name
Are you worried that in a year it will be missing a feature you want?
It's client side javascript, aside from DOM based XSS (which if reported, you can probably fix yourself), there isn't much to worry about from the security perspective. The web doesn't normally deprecate things so it's probably going to work in a year too.
This is a tiny project which already requires that you know JavaScript, so you can't even claim that you can't maintain it because you don't know the implementation language. It doesn't depend on some build step (which often is the thing that breaks after a year).
Exactly — that’s a good way to frame it. One of the reasons I kept Dagger.js tiny and runtime-only was to minimize those risks: no exotic build chain that might break, and nothing beyond plain JS/HTML that the web already guarantees to keep working. HTML + Web Components + a few attributes. That’s about as low-lock-in as a framework can get.
Totally fair — longevity is a real concern, and I’ve had the same hesitation with new tools myself.
The nice thing about Dagger.js is that it’s intentionally very small and HTML-first. If the project disappeared tomorrow, your markup is still just plain HTML + attributes, and your components are still standard Web Components. There’s very little “lock-in” compared to bigger frameworks with proprietary syntax or build pipelines.
That said, I do intend to keep it alive — it’s under active development on GitHub, MIT licensed, and easy for others to fork or extend. If a year from now it still looks useful, I’d be glad for you (and others) to take another look.:)
Positioning: Think Alpine/Vue-like ergonomics but no build and WC-first.
Size & perf: Focus is on simplicity and startup latency over framework features. I’m not posting synthetic benchmarks; if you have a real page you want me to try, I’ll profile it and share results.
Interop: Works with native Custom Elements. I’m preparing examples with Shoelace/FAST.
Security: Directives are sandboxed; no eval. If you spot an injection risk, please open an issue and I’ll patch quickly.
Limitations: Complex state management, SSR/streaming, and huge SPA routing aren’t first goals.
License: MIT.
Contrib: Issues and small PRs welcome (docs, examples, tests especially).
I’ll stay in the thread to answer questions and incorporate feedback into the docs.
Good catch — thanks for digging into that. You’re right: the domain still has a mix of A records (AWS + GitHub Pages), which explains why some people see different results.
I have removed the broken A records and the site works normally now. Appreciate the pointers and links
Haha, true — the front page doesn’t always need another JS framework
dagger.js is tiny and pretty niche compared to the “big ones,” but I figured it was worth sharing since it’s trying to go backward a bit: no build, plain HTML, Web Components. More of a “view-source-able” experiment than a contender for the next React/Vue.
Exactly, we also have to think about support and maintenance when building and shipping products. It's always nice to play with new things to keep the learning fresh and see what people are up to. I started with php and .NET Framework ASP and in the early-mid 2010's when the reactive JS frameworks started coming around I just never found my jive with them and just started working at C#/.NET shops and am using Blazor Server now. For my domain of web application development the .NET web application ecosystem works great. Looking at the dagger.js docs and examples found myself thinking, this is more Java(SCRIPT) development. It's going to inherit the same issues as JavaScript (weak typing, no runtime reflection, no binary build output, locked into vendor interpreters with mixed feature support), and that's not mentioning all the oddities with the way object prototypes are implemented and interact with each other. I think the ambition and result of the project are amiable. The author did good work, but it's good work on a thing we need less of in my opinion.
Really appreciate you taking the time to look through the docs and write such a thoughtful comment. You’re right — JavaScript carries a lot of quirks and limitations that aren’t going away, and if you’re building full-scale business apps in the .NET ecosystem, Blazor is a very natural fit.
dagger.js isn’t trying to compete with that class of frameworks. The goal is much narrower: keep a build-free, HTML-first option around for cases where shipping something lightweight, inspectable, and easy to embed is more important than squeezing out type safety or runtime guarantees.
I completely agree that we don’t need everybody moving deeper into JS just for the sake of it. But I do think there’s value in keeping a spectrum of tools alive — from strongly-typed/.NET style systems to small runtime-only JS libraries — so developers can pick the right trade-off for their domain.
Thanks again for the honest feedback; it helps clarify where this approach makes sense (and where it doesn’t).
Is this aimed at being in the same role as petite-vue and alpinejs? They also don't have a build step.
I've started to think something like petite-vue and twind would let you build small internal tools quickly, there are some major downsides to it which is why I haven't committed yet.
Yeah, that’s a fair comparison — Dagger.js lives in a similar space to petite-vue / Alpine: no build step, HTML-first, sprinkle behaviors where you need them.
The main differences are:
pure declarative mode → there is zero API and third-party code & tool dependency.
Web Components first → you can wrap functionality as native Custom Elements and Dagger will happily coexist.
Directive model → simple +click, +load, etc., instead of reactivity syntax or x- attributes.
Distributed modules → small script modules you can drop in from a CDN when you need them.
So it’s playing the same role (buildless, quick internal tools / embeds), but with a slightly different philosophy: keep everything view-source-able and make WC interop a first-class story.
Using the full vue.js doesn't have a build step either.
I started out developing UIs using petite-vue, unfortunately ended up rewriting it to use full Vue.js after running into too many of its limitations and issues, which given that it's abandon-ware wont ever be resolved. As such I'd strongly recommend against starting projects with PetiteVue and just use the ESM build of Vue.js which also doesn't require a build step, has the full feature-set, is actively used and maintained, etc.
Either way developing Web Apps (using Vue) without a build step using JS Modules is now my preference which I've written about in my Simple, Modern JavaScript post [1]
That’s a good point — the ESM build of Vue is solid, actively maintained, and does give you a no-build setup with the full feature set.
dagger.js aims a bit differently: it’s even smaller in scope (no virtual DOM, no reactivity system, no SFCs), and is designed to pair directly with Web Components and plain HTML snippets. The trade-off is fewer features, but also less surface area and almost zero “lock-in” — you can literally view-source and drop it into a page.
So I see them as different tiers on the same spectrum: Vue (ESM) if you want a mature, batteries-included framework without a bundler; Dagger.js if you just want minimal runtime directives and WC interop with almost no moving parts.
Appreciate you sharing the blog link — I’ll check it out. Always happy to see more people pushing the “modern JS without a toolchain” approach.
If I had to use one of these modern JS frameworks, I think Vue without build step would be one of the candidates. No shitty webpack configuring, no minimizer, no bundler, no friggin uglyfier, no juggling modules. None of the crap, just write your JS and serve the script, done.
Totally agree — the ESM build of Vue gives you a great “no-bundler” experience with a full framework behind it.
dagger.js sits in the same no-build space, but deliberately strips it down even further: no VDOM, no reactive system, no SFCs. Just HTML with attributes like +click / +load, and it plays nicely with native Web Components. The trade-off is fewer features, but also less surface area and almost nothing to configure.
So if Vue ESM is “full-featured without the tooling overhead,” dagger.js is more like “minimal glue you can drop in via <script> when you want to stay as close to plain HTML/JS as possible.”
That’s totally valid — if you’re comfortable living close to the DOM, zero-runtime + zero-build is the purest path.
dagger.js is meant for folks who want to stay mostly in plain HTML/JS but still smooth out a few of those DOM “sharp edges” — e.g. inline state with +load, simple event handlers with +click, template interpolation. The idea is to reduce boilerplate without hiding what’s really happening underneath.
So it’s less about abstracting away the DOM entirely, and more about lowering the friction for small tools/demos where you don’t want to write a ton of document.createElement calls.
1- the DOM APIs are very verbose, excepting perhaps replacing chunks by setting innerHTML, but
2- manual DOM manipulations aren't composable without also using web components
3- naive manual DOM manipulation can potentially be slow by way of triggering needless layouts/repaints or inefficient use of the APIs
Web components didn't exist when the major frameworks came about, and the ones before them handled composition rather poorly if at all (such as backbone). Angular, ember, react and company all sought to provide a cohesive story for code reuse and composition. Many had their own performance stories, though it was always a secondary concern to everything else.
I've done a bit of everything, including pure vanilla JS, just jQuery, vanilla + web components, all the way up to next, ember, angularjs and angular, and more. If you're building a web site, vanilla JS is fine. If you're building a web "app", you'll pretty quickly appreciate what a framework can bring to the table. If you don't, you'll also quickly find yourself building your own mini framework and runtime to manage things.
Well put — that lines up with how I see the ecosystem too. For small sites, vanilla JS is fine; once you move toward “app,” you either reach for a framework or start reinventing bits of one yourself.
dagger.js is basically me leaning into that middle ground: accept the verbosity/sharp edges of the DOM, but try to smooth just enough of them with directives (+click, +load, interpolation) so you don’t accidentally start building your own mini framework. It stays runtime-only, works directly with Web Components for composition, and tries not to hide what’s really happening under the hood.
So it’s not aiming to replace React/Angular, more to give people a lightweight option before they hit the point where those make sense.
In dagger.js interpolation is scoped to attributes and text nodes — anywhere you put ${…} inside the HTML markup, the expression is evaluated against the current directive scope.
In your sample code, winner is looked up from the nearest +load directive context. Interpolation isn’t “everywhere” JS-style, it’s only applied to the DOM text/attribute content that Dagger processes. Actually it's standard string template in JS.
You may also use the text directive instead to avoid using inline expression:
<div class="text" text="`${ winner ? 'Wins' : 'Draw' }!`">
</div>
Shameless plug to my own runtime (and compile) micro framework: https://github.com/fresho-dev/mancha
And nice, Mancha looks cool — I’ll give it a read and star. It looks similar with dagger in some features, for instance, mancha uses :data to create scope while dagger uses +load directive. Always great to see other takes on the runtime/compile spectrum; I think having multiple approaches out there is healthy for the ecosystem!
I think your site broke? Also, I'd scoop up daggerjs.com while you're at it.
Some time ago while I was experimenting with writing Debian benchmarks[0], I found that by completely avoiding strings, using Uint8Arrays, and manually managing bounds/memory, I could squeeze out performance that almost made you forget you were writing JavaScript. I never ended up submitting a PR, but it was pretty eye-opening.
At one point I went into a rabbit hole and tried to build something similar on my own, but it got complicated very quickly given my limited compiler knowledge. That’s why I always thought Prepack[1] was such a cool idea.
[0] https://benchmarksgame-team.pages.debian.net/benchmarksgame/... [1] https://github.com/facebookarchive/prepack
The big difference is that Svelte achieves that by compiling away the framework, whereas Dagger.js avoids compilation entirely. You don’t install a CLI, you don’t run a build — you literally drop a <script> from a CDN and wire up directives in plain HTML. It’s closer to Alpine/htmx in that sense, but with a focus on working alongside Web Components.
So in spirit, yes — both try to reduce overhead. Svelte optimizes post-build output; Dagger.js tries to remove the build step altogether.
Here is a dagger.js version Hello world demo:https://codepen.io/dagger8224/pen/raOXxee?editors=1010
Right, but that is what basically every JS framework is going for these days. Its refreshing to see somebody trying to go back to old school non-compiled js/html where every front-end is open-source(ish)
+1, I genuinely miss php-like template development.
Can't believe there is no modern take on such a simple and powerful approach.
I feel like powerful php-like templating with typed props, proper module resolution, etc.
I really hope you will try using dagger.js and come back to tell me how you feel about it. Thanks!
https://solidjs.com
dagger.js is coming from the opposite direction: no compiler, no JSX, and also no signals. just plain HTML with attributes like +click / +load. You drop in a <script> from a CDN and it wires up behavior at runtime. It’s more about zero build friction and “view-source-ability”than squeezing out maximum perf.
So if Solid is about compiling React-like ergonomics down to efficient DOM transforms, dagger is about skipping compilation entirely and letting you glue components together with HTML. Two very different trade-offs, but complementary ends of the spectrum.
dagger.js isn’t trying to chase those kinds of deep compile-time optimizations. Its focus is the opposite trade-off: keep things build-free, HTML-first, and easy to drop into a page. I’d rather leave the heavy lifting to whatever compiler or bundler someone pairs it with, and make sure the runtime layer stays simple and transparent.
So in my mind these approaches complement each other: advanced compilers make large apps faster; Dagger tries to make small apps and prototypes friction-less.
Link to the DI mentioned by the parent comment https://github.com/google/dagger (also Apache 2)
Once this project is about a year old, if it still has any commits, then I'd consider it.
Are you worried that in a year it will be missing a feature you want?
It's client side javascript, aside from DOM based XSS (which if reported, you can probably fix yourself), there isn't much to worry about from the security perspective. The web doesn't normally deprecate things so it's probably going to work in a year too.
This is a tiny project which already requires that you know JavaScript, so you can't even claim that you can't maintain it because you don't know the implementation language. It doesn't depend on some build step (which often is the thing that breaks after a year).
The nice thing about Dagger.js is that it’s intentionally very small and HTML-first. If the project disappeared tomorrow, your markup is still just plain HTML + attributes, and your components are still standard Web Components. There’s very little “lock-in” compared to bigger frameworks with proprietary syntax or build pipelines.
That said, I do intend to keep it alive — it’s under active development on GitHub, MIT licensed, and easy for others to fork or extend. If a year from now it still looks useful, I’d be glad for you (and others) to take another look.:)
Positioning: Think Alpine/Vue-like ergonomics but no build and WC-first.
Size & perf: Focus is on simplicity and startup latency over framework features. I’m not posting synthetic benchmarks; if you have a real page you want me to try, I’ll profile it and share results.
Interop: Works with native Custom Elements. I’m preparing examples with Shoelace/FAST.
Security: Directives are sandboxed; no eval. If you spot an injection risk, please open an issue and I’ll patch quickly.
Limitations: Complex state management, SSR/streaming, and huge SPA routing aren’t first goals.
License: MIT.
Contrib: Issues and small PRs welcome (docs, examples, tests especially).
I’ll stay in the thread to answer questions and incorporate feedback into the docs.
Thanks
https://www.whois.com/whois/3.33.130.190 and https://www.whois.com/whois/15.197.148.33 are AWS
https://www.whois.com/whois/185.199.109.153 and similar are GitHub and is almost certainly this repo https://github.com/dagger8224/dagger8224.github.io/blob/main...
I have removed the broken A records and the site works normally now. Appreciate the pointers and links
Will check out the repo linked at the end of your message.
dagger.js is tiny and pretty niche compared to the “big ones,” but I figured it was worth sharing since it’s trying to go backward a bit: no build, plain HTML, Web Components. More of a “view-source-able” experiment than a contender for the next React/Vue.
dagger.js isn’t trying to compete with that class of frameworks. The goal is much narrower: keep a build-free, HTML-first option around for cases where shipping something lightweight, inspectable, and easy to embed is more important than squeezing out type safety or runtime guarantees.
I completely agree that we don’t need everybody moving deeper into JS just for the sake of it. But I do think there’s value in keeping a spectrum of tools alive — from strongly-typed/.NET style systems to small runtime-only JS libraries — so developers can pick the right trade-off for their domain.
Thanks again for the honest feedback; it helps clarify where this approach makes sense (and where it doesn’t).
I've started to think something like petite-vue and twind would let you build small internal tools quickly, there are some major downsides to it which is why I haven't committed yet.
The main differences are:
pure declarative mode → there is zero API and third-party code & tool dependency.
Web Components first → you can wrap functionality as native Custom Elements and Dagger will happily coexist.
Directive model → simple +click, +load, etc., instead of reactivity syntax or x- attributes.
Distributed modules → small script modules you can drop in from a CDN when you need them.
So it’s playing the same role (buildless, quick internal tools / embeds), but with a slightly different philosophy: keep everything view-source-able and make WC interop a first-class story.
I started out developing UIs using petite-vue, unfortunately ended up rewriting it to use full Vue.js after running into too many of its limitations and issues, which given that it's abandon-ware wont ever be resolved. As such I'd strongly recommend against starting projects with PetiteVue and just use the ESM build of Vue.js which also doesn't require a build step, has the full feature-set, is actively used and maintained, etc.
Either way developing Web Apps (using Vue) without a build step using JS Modules is now my preference which I've written about in my Simple, Modern JavaScript post [1]
[1] https://servicestack.net/posts/javascript
dagger.js aims a bit differently: it’s even smaller in scope (no virtual DOM, no reactivity system, no SFCs), and is designed to pair directly with Web Components and plain HTML snippets. The trade-off is fewer features, but also less surface area and almost zero “lock-in” — you can literally view-source and drop it into a page.
So I see them as different tiers on the same spectrum: Vue (ESM) if you want a mature, batteries-included framework without a bundler; Dagger.js if you just want minimal runtime directives and WC interop with almost no moving parts.
Appreciate you sharing the blog link — I’ll check it out. Always happy to see more people pushing the “modern JS without a toolchain” approach.
dagger.js sits in the same no-build space, but deliberately strips it down even further: no VDOM, no reactive system, no SFCs. Just HTML with attributes like +click / +load, and it plays nicely with native Web Components. The trade-off is fewer features, but also less surface area and almost nothing to configure.
So if Vue ESM is “full-featured without the tooling overhead,” dagger.js is more like “minimal glue you can drop in via <script> when you want to stay as close to plain HTML/JS as possible.”
Personally I rather have zero runtime code along side zero build by learning truly native js dom
dagger.js is meant for folks who want to stay mostly in plain HTML/JS but still smooth out a few of those DOM “sharp edges” — e.g. inline state with +load, simple event handlers with +click, template interpolation. The idea is to reduce boilerplate without hiding what’s really happening underneath.
So it’s less about abstracting away the DOM entirely, and more about lowering the friction for small tools/demos where you don’t want to write a ton of document.createElement calls.
1- the DOM APIs are very verbose, excepting perhaps replacing chunks by setting innerHTML, but
2- manual DOM manipulations aren't composable without also using web components
3- naive manual DOM manipulation can potentially be slow by way of triggering needless layouts/repaints or inefficient use of the APIs
Web components didn't exist when the major frameworks came about, and the ones before them handled composition rather poorly if at all (such as backbone). Angular, ember, react and company all sought to provide a cohesive story for code reuse and composition. Many had their own performance stories, though it was always a secondary concern to everything else.
I've done a bit of everything, including pure vanilla JS, just jQuery, vanilla + web components, all the way up to next, ember, angularjs and angular, and more. If you're building a web site, vanilla JS is fine. If you're building a web "app", you'll pretty quickly appreciate what a framework can bring to the table. If you don't, you'll also quickly find yourself building your own mini framework and runtime to manage things.
dagger.js is basically me leaning into that middle ground: accept the verbosity/sharp edges of the DOM, but try to smooth just enough of them with directives (+click, +load, interpolation) so you don’t accidentally start building your own mini framework. It stays runtime-only, works directly with Web Components for composition, and tries not to hide what’s really happening under the hood.
So it’s not aiming to replace React/Angular, more to give people a lightweight option before they hit the point where those make sense.