Show HN: Nue – A React/Vue/Vite/Astro Alternative (nuejs.org)
I'm releasing two things today:
1. Nue JS: https://nuejs.org/docs/nuejs/ — A tiny (2.3kb minzipped) JavaScript library for building user interfaces. It's like React/Vue core, but there are no hooks, effects, props, or other unusual abstractions on your way. Know the basics of HTML, CSS, and JavaScript and you are good to go. Nue JS supports server-side rendering (SSR), reactive components, and "isomorphic" combinations. It takes inspiration from Vue 2.0 and Riot.js. (I'm actually the original author of Riot).
2. Nue ecosystem: https://nuejs.org/ecosystem/ — This is the ultimate goal and once all the sub-projects are finished, Nue will be a serious alternative to things like Vite, Next.js, and Astro.
The thing is that I'm not happy with the current state of web development, so I want to write a completely new ecosystem from scratch. I'm taking advantage of the "old" innovations like progressive enhancement, separation of concerns, and semantic web design. Benefits highlighted here: https://nuejs.org/why/
All projects will be released under the MIT license.
Happy to answer any questions.
311 comments
[ 3.4 ms ] story [ 366 ms ] threadLike you, I dislike much of the modern web frameworks and all the bloat and unnecessary complexities that come with it. I roughly tuned out of this stuff when JQuery became mainstream and everyone and everything started using it, and I couldn't be bothered to keep up any more, nor did I feel inclined to invest my time in such a bloated framework. I did come back to webdev every now and then for casual projects, but every time I did, the world moved from one fad framework to the other, which made me dislike this messy ecosystem even more.
In particular, one environment/toolset that I really disliked was Node.js. Every time I did anything with Node, it always turned into pulling down a gazillion dependencies, and eventually down the line, that led to stuff breaking because some random dependency of a dependency was no longer compatible a with newer version of node or something. It basically put me off modern webdev for good, to the extent that I web back to using plain ol' php for the backend, and since then I've been exploring using pure HTML5+CSS3 without any Javascript for the frontend, but I've been seeing limitations like not being able to do stuff like real-time form validation etc.
Which brings me to your example:
May I enquire why you're using npm here? Exactly what dependences are you pulling down? I thought the whole point of Nue was to avoid bloat like Node.js and dependency hell? Isn't Nue supposed to be a self-contained library/ecosystem?Can I use Nue without touching any Node stuff at all?
Node uses a single dependency, htmlparser2 [1], in the package.json [2]. The HTML parser is used to traverse the HTML that is written on the Nue files. I quickly _thought_ of writing my own parser, but right now I'm having my eyes staring at Bun's native HTML parsing capabilities. Instead of Node, I'm using Bun to develop everything. I need less dependencies with it, because things like JS minification or .env file parsing are biult in.
Avoiding NPM dependencies is a high priority!
[1]: https://github.com/fb55/htmlparser2
[2]: https://github.com/nuejs/nuejs/blob/master/package.json#L12
[3]: https://github.com/oven-sh/bun/discussions/1522
[1]: https://bradfrost.com/blog/post/front-of-the-front-end-and-b...
However, it is more like an alternative to Petite-Vue or Riot.js rather than full-blown Vue or React. Therefore your comparison vs headlessui-react/vue is like apple vs orange/banana: headless UI listbox is much more complicated than your implementation. You can easily make a listbox in Vue using a similar amount of code as Nue.
One thing which is lacking in your Getting Started (https://nuejs.org/docs/nuejs/getting-started.html) is how to use Nue without a build step, in order to progressively enhance existing HTML websites like Petite Vue: `<script src="//unpkg.com/petite-vue" defer init></script>` or Alpine.js: `<script src="//unpkg.com/alpinejs" defer></script>`?
How is Nue performance compared to other JS frameworks? Could you add it to https://krausest.github.io/js-framework-benchmark/current.ht...?
You are right: Nue takes inspiration from Vue 2.0, petite-vue and Riot.
I'll make the comparison more fair, but it doesn't take out the fact that React/Vue promote use of "spaghetti" code where logic/layout/styling are mixed together making the code hard to read and causes the size to grow. Everywhere I look the projects are unnecessarily big. Very often in the factor of 10x too big.
Pretty sure Nue JS will always need a build step. I don't like the idea to load the compiler and run JS exec() on the client side. Heavy and unsecure.
Haven't checked performance yet. I want to see this project getting more traction before deep diving to benchmarking
Probably not intentionally deceitful, but it a ridiculous comparison.
However, according to BundleJS, only nuejs-core's compile() method is 36.2KB minified gzipped: https://deno.bundlejs.com/badge?q=nuejs-core@0.1.0&treeshake... - it is nowhere close to 2.3KB as on your website. Compare it to petite-vue's bundle, which is only 7.3KB: https://deno.bundlejs.com/badge?q=petite-vue@0.4.1
https://nuejs.org/@nue/js/nue.js
local gzip on my machine is 2.3kb
It’s very cool. I’m on my phone, but I’d like to investigate more later.
Please add a mailing list to the homepage so I can keep up to date with your progress. A blog with smaller updates would be nice also.
Not a fan of the Vue template syntax but it's not a deal breaker.
I really love that you don't need a bundler.
* Search—in the Headless UI version there are several hundred lines dedicated to making typing work for jumping to specific list items.
* Multiselect—Headless UI supports multiple selections, yours does not appear to. Again, this accounts for a large number of extra lines in the Vue implementation.
* Focus management—Headless UI has a lot of code dedicated to smoothing out the focus management. In my testing, your implementation has pretty buggy support for using tab to navigate.
* The Headless UI version dedicates a lot of lines to types, where your Nue implementation is dynamically typed. This may be a feature for you, but in my mind those type declarations are doing important work.
* In general, the Headless UI implementation tries to be flexible for many use cases [1], while yours only needs to support the one demo list.
These kinds of comparisons are most persuasive if you can write all the implementations from the ground up, using idiomatic patterns for each framework and identical feature sets for each implementation. When you do that, it's easy to compare and contrast the frameworks. As it is, it's like comparing a house to a garden shed: yes, you've used fewer lines of code, but it's not obvious to me that that's a feature of Nue and not just a byproduct of a less ambitious component.
[0] https://nuejs.org/compare/component.html
[1] https://headlessui.com/vue/listbox#component-api
> Amount of code needed for a rich, interactive web page.
And lists "Tailwind CSS" as 804k.
As a reminder, Tailwind CSS doesn't require or use JS in the browser at all and the majority of tailwind gets removed during build so the vast majority of the code you're attributing to Tailwind CSS is unrelated to the task of using Tailwind to build a rich interactive webpage.
To your point about inlining styles, using Tailwind out of the box I struggle to see how you're forced above 14kb, and if you really had kilobytes of classes in your markup you can switch to composing your own rules with @apply.
I recognize you are making a tool and not trying to do ecosystem wide benchmarks, but still suggesting you need 804kb to use Tailwind still seems disingenuous, or at least misinformed, to me.
Maybe someone at this large, segment leading company carefully considered that they should have 12 different srcset pictures because "responsive" and "bandwidth", but I doubt it because the URLs violate DRY and have escaped characters in the query part and the URL indicates this brand doesn't host static content on their own server (as in, they've hired someone el...
If you're asynchronously loading something, why are you loading divs, and not JSON which you then display on the page?
> fter the front page is presented, so the first thing visitor sees is a quick loading page, the 2 to 4 second load happens in the background, they click a link, BOOM next page loads in its full-featured, one-or-two-human-readable-class-per-element glory with the Sneaky Load Giant CSS as an already-cached dependency.
This has nothing to do with Tailwind, css classes, or even JS frameworks.
> outside of every paragraph (instead of a single, well-defined paragraph class that could even inherit common custom properties)
Again, this has nothing to do with Tailwind, and everything to do with:
- CSS sucks at components
- CSS sucks at scoping
- CSS sucks at nesting
- CSS sucks at namespacing
Literally nothing is stopping you from applying a global style even if you use Tailwind. Moreover, the authors of CUBE methodology [1] suggest Tailwind for utility classes [2]
[1] https://cube.fyi
[2] https://buildexcellentwebsit.es
Ultimately Nue will come out with a UI library with a high feature parity with Headless UI. I can imagine the current listbox (demo) doubling it's size with all the above features. Definitely not 10x!
This will actually be a killer addition. I was actually complaining about this the other day: https://news.ycombinator.com/item?id=37448914#37449926
All up, it’s just like so many others, a bad reimplementation of half of what the browser already provides with <select>. About the only thing it adds to that is support for an image per option, and perhaps some more exotic styling aspects (which you hopefully don’t want anyway).
Mind you, I do find Headless UI generally bloated, mostly just suffering from being overly flexible, and it does end up with a moderate amount of code bloat attributable to the particular frameworks’ designs (though not as much as some I’ve seen), but the comparison is just unreasonable. If they think it’s fair to say “With React: 2.5k lines; with Nue: 200 lines”, then I respond: “With HTML: 0 lines”, and insist that <select> is better than the result of those 200 lines.
There are more problems with it, too, whereas I suppose Headless UI will be a pretty high-quality implementation. Examples of problems I found immediately, without having tried to actually run it, but which I presume Headless UI will be free of: it uses <menu> for the options and wraps each option’s label with <strong>, which are both semantic sins; some of the code sharing with combo boxes leads to obvious minor inefficiency (filtering, which can’t actually happen); Escape detection happens on keyup instead of keydown; clicking outside the listbox popup won’t close it if the target or an ancestor matches .open, which is very plausible, e.g. when within a modal dialog (and because it’s ad hoc, it’s certain to interact badly with things like clicking outside modals—any concept of potentially-nestable modality needs to be managed more than that, in one of a few ways but I’ve already rambled enough); after pressing Escape to close the popup, pressing Tab will reopen it as well as moving to the next focusable.
Hopefully the problems with this will be sorted out, but at present I think it’d be best to just remove the comparison, because it portrays a false picture, and suggests that the listbox is ready for use, whereas I hope that the author would agree it’s not.
[1]: https://headlessui.com/react/radio-group
If the reader wonders where these lines were saved, they will only find broad, general statements about (IMO questionable) values. Compare this to some other frameworks, where the changes from the status quo are clear on the landing page:
- Svelte -> compile step, templating, common features included
- Solid -> signals, constructor functions
- Lit -> web-components, fewer features
It is unfortunately common for new frontend solutions to not be as up-front about their trade-offs as I would like. But this takes the cake for most requirements swept under the rug.
Yeah this is actually a little scary:
https://nuejs.org/compare/faq.html
> No TypeScript: Nue embraces the dynamic typing in JavaScript
I for one have no desire to fight dynamic Javascript spaghetti any more. I personally think Typescript types aren't strong enough! (Too much `as Foo` around.)
https://nuejs.org/docs/nuejs/component-basics.html#slots
I'm unable to see the relationship between the <slot /> tag and the looped content in the 2nd code snippet. Can you clarify that in the documentation?
Edit: I think it would have made more sense if you included the @name="media-object" attribute in the first snippet.
I only figured it out by looking at the previous section's code before slots to see that attribute and noticed that the slots example first snippet was missing the attribute I mentioned that would connect the pieces together
I can see that the slots example needs improvement and more detail. I'll make it shine because slot is such an important feature and helps you build reusable code.
I'll work on the docs as a whole, now that I'm getting this valuable feedback from here.
Why go through that whole progress again with Nue? Or do you foresee some other way of doing highly customizable components?
[1]: https://css-tricks.com/the-great-divide/
Rethinking things from the ground up and making it smaller and more RAM efficient, is absolutely brilliant.
More frontend devs needs to stop following the herd and think for themselves and look back at how hackers used to work back in the day to use as little memory as possible.
These days I look at apps like Slack and feel such terrible sadness and despair.
Projects like Nue at least have the right spirit and attitude.
I want to make things very, very differently. Not just because of the size, but maintaining a codebase with 5k lines is so much easier than maintaining 500k lines.
I don’t know what the solution is there.
Question is how we get web developers to learn those, instead of the next (ha) hyped JS frontend frameword.
I'm all about caring and using resources efficiently, and in a sense that's how we get such inefficient tech even though it's not what I mean. Money defines efficiency, and we're getting heavy apps for pretty cheap while lighter apps are more expensive in terms of specialized labor costs.
If engineers with this right attitude collectively work for rates competitive with global head shops and still deliver as quickly then we can have our light weight app cake and eat it too. I'm personally selling my services for $15/hr already, and anyone who hires me will get a pretty well engineered solution with minimal dependencies; who's with me?
Kudos to the author, the best thing about this is that the source is concise!!
Will people avoid adopting them because code won't be auto-generated efficiently?
It wouldn't be a barrier for me or many people that read hacker news, but I suspect there is a growing subset of the developer community for who this would be an issue.
If you're thinking, all we have to do is wait for OpenAI to re-scrape the web and re-train GPT on the new material, well... LLMs don't "learn" so much by looking at documentation, as by looking at examples. And a new tool is not going to have a lot of examples out there, simply by virtue of being new.
The "Selfish Gene" strikes again.
Aside, this is not going to stop people learning and using a language if it provides benefits. Not everyone is on the AI hype train. I personally couldn't care less - I don't trust any current AIs to write correct, bug-free code and so I just avoid them. Then again, I also don't trust most humans to write bug-free code and I tend to avoid them too. Formal verification should be the way forward, and this is why new languages, which can embed proofs, should continue being developed and improved, ignoring the AI hype.
When the AI can write code in formal verification languages, I might consider it.
Personally, I'm waiting for the space to settle, and for an offline, self-hosted and OSS version to reach feature parity with the proprietary SaaS offerings. Those might exist already, I'm not evaluating the options frequently, but I'm in no hurry.
On-topic: NueJS looks interesting. I'm very worn out and weary of shiny new JS frameworks, but I like the simplicity here. Will keep an eye on the project and consider it again once it matures, but for now Svelte is my best friend.
If you introduce a feature where someone writes
and the IDE goes, "Hey dude, probably writing a loop, should I manage that for you?" and it's C++ 17/20/23 or Rust or Go best practice and looks back a little bit in your code and in its compendium of great project examples to see what the loop logic should/could be...I would probably let the IDE write the loop header for me. And the string formatting. And modify the function I'm writing to support multithreading. And tell me it looks like I was trying to change each instance of pxX to pxY and graphX to graphY but also forgot to change one rotX to rotY.
Hell, if the IDE could read a PDF datasheet and automatically import addresses and bitfields and assign them to variable names, much of my current career workflow would be automated and I could focus mental effort on more creative work.
Autocomplete is far less intrusive, and doesn't fall into this category. I can quickly refine the results since the scope is greatly reduced, and I don't have to read a large chunk of code to understand whether it does what I want it to do, or whether it introduces subtle bugs I'll have to hunt down later. Besides, we've had code snippets, macros and refactoring tools for decades to help with writing code quickly, so AI tools are not groundbreaking in that sense.
Even once AI tools are absolutely correct in guessing my intention, and write entirely bug-free code, I think I'll still prefer typing code out manually. By that point, AI will be capable of writing complex programs from prose prompts, so that creative work you mention will also be automated away. Yet human programmers will still exist in some form, if nothing for the joy of it. We'll probably value programs written by humans in the same way we value handcrafted tools that are not mass produced today.
``` <div @name="media-object" class="{ type }"> <img src="{ img }"> <aside> <h3>{ title }</h3> <p :if="desc">{ desc }</h3> <slot/> </aside> </div>
<div class="art-gallery"> <media-object :for="item in items" :bind="item"/> </div ```
I really don't like the opinionated, magical/weird syntax (like vue's :@v-for-OnClick="fn()"), I prefer how close and true to vanilla html/js react is, rather than stuff like this.
I can understand that this syntax is not a preference for JavaScript/TypeScript developers who opt to JSX and want to write everything (logic, layout, styling) in JavaScript.
https://developer.mozilla.org/en-US/docs/Web/API/Element/cla...
https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelEl...
I'm not sure that the compilation aspect is relevant - pretty much all modern frameworks using a template language have a compilation step. ngFor doesn't exist in the browser after all! ;)
The goals of this project and Svelte seem very similar, so I'd be interested to see a more in-depth comparison.
Its name should always start with `use` so that you can tell at a glance that the rules of Hooks apply to it.
And it is required and enforced if you use the ESLint react-hooks plugin (which I'm guessing most large projects do).
I just looked at some Svelte examples and it's a mix of magic keywords (on, bind) with magic symbols (: | @) and new, completely unrelated syntax to both JS and HTML (#each, #if, :else). I guess it looks way more idiomatic if you have an IDE that highlights and lints it correctly. React with its few rules of hooks seems way closer to vanilla JS.
>Bring back the power of cascaded styling
Welp, I'm out.
And now we have native nesting, wich was in old times a reason for use things like sass/scss/... CSS-Variables too, so theming is not a pain in the a.. anymore.
You can use overbloated frameworks, but i did not see a reason anymore for that. Especially when you develop component based. Tailwind on a top level is ok, but not within a component and child items, unnecessary complicated.
It’s almost as if there’s a reason for this.
Classic HTML is pretty good for building static websites, but it sucks for building interactive applications.
https://nuejs.org/compare/faq/
https://codebase.show/projects/realworld
https://medium.com/dailyjs/a-realworld-comparison-of-front-e...
Are you really planning to create a new build tool?
While you may not need it, everyone else may have different needs
Is this idiomatic? I refused to use React for years, but if this is normal-ish, it basically cements the decision. An implementation of a ListBox in VGA 0xA0000 framebuffer could be only a little bigger (if even bigger). GtkTreeView, which draws a complete tree/table with columns, resizing, dynamic rows and all the interactions, was 10kloc, afair (now 14). GtkCombobox.c is 5kloc, almost half of that is comments or doxygen.