Interesting. I use full Vue for this quite a lot, mount onto specific DOM points, replace their content with (most commonly) an enhanced form, or a data table. Works well, costs 30Kb plus compat layers. You can argue all day long about the cost of 30Kb, but then you put a 200Kb image in your header.
Anyway, looking at the docs, my approach wouldn't be as easy in vue-petite. It looks like Components have been functionally gutted. You can still approximate something, but you seem to lose a lot of ecosystem benefits of Vue. Theirs looks great for
Ultimately, this all seems like something coverage and tree-shaking should be able to do. If you're only using 5Kb of Vue, only 5Kb should be bundled. One day, eh? Until then, is the additional 25Kb actually hurting your users?
Until then, is the additional 25Kb actually hurting your users?
Not really.
Nor is an extra 30KB font file.
Or an additional 50KB for an icon set.
Or an extra 18KB for a better select box.
Nor is that 200KB header image.
Why not add that 50KB analytics script too?
The extra 40KB for a nice a animation library is useful.
You need to add 150KB for a UI component library.
And so on, all the way until your page is a 2MB download..
Any individual incremental increase can be justified as part of the page weight, but a few KB here, a few more there, and your site suffers death by a thousand cuts. You have to worry about the extra 25KB here and there if you're going to keep the overall size within a sensible performance budget.
I absolutely agree with the gross sentiment —CPU time and bandwidth are expenses that should be argued— but your argument omits two key items: developer time and UX benefit.
In my case, using full-fat Vue lets me do a swathe of complex stuff, pulling in libraries and components we use elsewhere, that also do piles of complex stuff, and it only takes me a couple of hours to progressively enhance a big form, which makes it nicer for the user with pro-active validation, breaking the thing into a wizard, easy dynamic lookups, etc. My work increases conversions, creams KPIs.
Is that worth 30KB? Every day of the week.
Can I batter it down to 20KB? Probably, but it'll take me at least twice as long this time, possibly make the work output less reusable and cost the client twice as much. Is that 10KB worth it? Maybe, maybe not.
Don't get me wrong, I'm not the sort of person who throws JS everywhere. I'm a Django developer who will always push to SSR over SPAs... But I also realise there is occasionally a business case for a but of reasoned splurging. Again, my hope is that within a couple of years tree-shaking gets good enough to automate this nonsense, trim out everything that isn't used.
200kb image doesn't block rendering, and while somewhat important, it's not the content the user came to see. 30kb might not be much, but this has to be downloaded, parsed, compiled and executed. These 30kb fight for bandwidth and CPU with other resources or even apps running on the same machine. Sometimes it's fine, but sometimes... Sometimes one component is generated only after another one has loaded, which itself depends on other components, each of which might depend on other resources. It might get pretty bad really quickly. Usage of JS when done right is fine, but it's really easy/convenient/common to do it badly.
For the little it's worth, my 30KB+ full-Vue progressive enhancements don't render block either. It's happening after DOMContentLoaded fires, replacing "real" content with Vue content. And yes, they use more CPU and RAM than -petite. My point there was that a lot of people focus on a bandwidth argument while their sites use [comparatively] massive blobs of media. 3MB bitmap image on their CMS uploaded by Sean in marketing because he doesn't know any better. That sort of thing.
Broadly speaking, I don't disagree. There's a lot of truly awful JS out there, wasting cycles doing things that CSS should be handling, but I think the tooling is slowly getting better.
I think that package size is a useful gut check about how you're delivering your web app. It's hard to screw up delivering a 100kb package, but it's pretty easy to screw up delivering 5 megs. You can probably also deliver 5 megs in a way that doesn't block anything - but you may not need to devote eng resources to doing that until you reach a certain package size.
I think it's supposed to work that way in Vue 3 as you don't import the full Vue script anymore.
Also as long as we're talking about Vue, people that have Vue 2 apps and missed the 3.1 release announcement (I don't remember seeing it on HN's frontpage) should check it out, there is a compatibility layer that works really well to migrate progressively.
Unfortunately the major blocker (for me) is the lack of IE11 support and the bloody paying customers who refuse to move off IE11. One day they'll be gone.
If anyone of you guys have access to Vue mastery watch the tutorial where Evan creates a mini-version of Vue js in vanilla JS in like 15 minutes.
He also explains some of the Vue optimization tricks like why they ditched the nested JSON and how Vue caches the @click handlers, etc so they don't need to check this on every digest cycle.
I wish there was a free version to link here. Really interesting stuff, shows you how much thought and effort is put in by the creators to optimise so many little things which us users of the framework never even notice is happening.
This progressive enhancement is exactly why I prefer Vue and find it so productive. 95% of apps are best built as server-side rendered with reactivity on top of each page as needed (instead of the JS/SPA monstrosities we have today).
Nice to see an even lighter version optimized for this use-case.
Vue doing this is awesome, but it isn't really a good reason to prefer it. Server side rendering with progressive enhancement is available in pretty much every major JS framework. Heck, the latest version of React can do SSR with late loading and late binding to make content load even faster. https://github.com/reactwg/react-18/discussions/37
Vue is specifically better because it uses HTML-based templates by default, and HTML is what's produced by web frameworks. This means you can use whatever technology you want on the backend and everything works seamlessly.
Also the syntax for directives, handlers, and other logic in these templates is much easier than dealing with JSX in the majority of uses-cases.
SSR/isometric rendering isn't new, but it's usually hacks around using a frontend JS framework to run the backend and can result in the worst of both worlds. Projects like Blazor (.net) and Livewire (php/laravel) are interesting new solutions to fix this.
In a lot of cases it's easier, true, but for other cases it makes things a lot harder. E.g. - how do you conditionally wrap some elements in another element? It's easy in React (assign the subtree to a variable), but impossible to do cleanly in Vue.
That is a general theme, I've found - compared to React, Vue makes the easy things easier, but the hard things harder.
<SomeElement
v-for="item in items"
v-if="display"
@click.prevent="foo()"
:class="{'current': active}" />
Not only the react blob is impossible to scan, but it will be different depending of the dev who coded it, because there is no enforced patterns. You must use brain power to parse every single template line. HTML, that thing that was simple and declarative, now becomes complicated and imperative.
And that's not even weird or unusual code. That's regular stuff one writes all the time. Don't get me started on state management or spaghetti hooks.
I have yet to work on a react code base I was more productive than on a vue one. And the gaps get wider if the team is not composed of excellent coders, because react code by junior is a nightmare.
Well, the fact that you're "just using javascript" in jsx does also mean that you need to format things nicely to avoid having an unreadable mess. Using a code formatter like Prettier helps a lot. The "react blob" is less of a blob if nicely indented.
Admittedly due to the nature of Vue syntax, it's harder to make a mess because everything is just key/value.. but then you have to learn an API to express things in that way. I enjoy the fact that you don't have that layer/step with react.
I definitely feel that the 3rd party classnames package should be built into React, I agree that out of the box conditional class names look a mess.
I don't have enough experience with either library yet to form an opinion on which I prefer, but I definitely appreciate not having the mental overhead of remembering the vue api. I'd rather have a bit of code that's more explicit/"just javascript" than have to think "what's that symbol I need to use again?". Definitely a personal preference thing though!
That's still a blob, just a longer one, with an additional dependency and more parenthesis to mess up. It's a compromise, not an improvement.
And in the end, I still have to read 2 JS expressions before even figure out what DOM element I'm actually dealing with. Then I still have to evaluate what the heck is happening in onClick and className.
I still have to parse code in my presentational layer, code that is interleaved with my template indentation so it also makes it hard to understand hierarchy and easy to make mistakes.
Of course, the elephant in the room we are not talking about with react is that all those things compounds. When you have 5 of such blobs in your render functions, issues don't add up, they multiply.
Then you add the store system on top of it, with actions, reducers and all that fun stuff.
Vue has vuex, so there's a need for actions and reducers. React state has become much simpler with packages like zustand and it works wonderfully with typescript.
It's not really that big of a deal to have another import. Vue's directive's (not sure if that's the correct term) are a mix bag of magic strings that tie to functions somehow. Why can't they just be a function variable like in React? The answer of course is there are smart people and smart users behind both projects and those are the trade-offs we tolerate.
Vuex is vastly less necessary for vue projects than redux for react projects. I've been coding in react and vue for years, it's not even on the same planet: before Vuex we never even needed a store, just import a component, that's your model.
But even so, Vuex way better integrated, requires less boilerplate (thanks vue reactivity) than redux, or even zustand, which once you add immer, looks like blobbing all over again.
Honestly, we should do a contest. Take 10 juniors out of school give them a twitter clone to write, 5 in Vue, 5 in React, and come back in a week.
In fact, no need for them to be junior. Let's just take your regular Java dev. Not your 10X HN dev. Just average Joe. See how it goes.
We've been doing something similar at our company when hiring. The tasks are simple:
1) Build a clone of a site or implement a design with their tool-of-choice (basic competency). For the ones who opt to start without frameworks, we also get a glimpse at how good their organization skills are.
2) After they are done, we give them several "requirement changes" and see how well/fast they adapt. People can trumpet whatever best practices they believe, but this is the part of the interview where some best practices are more practical than others.
3) Modify an existing project. Here, we pick the opposite of their preferred stack/methods. ie, if they prefer vue, we give them a react or svelte app to modify. If they prefer BEM, we give them functional (we use tailwind); if they prefer utility-first, we give them BEM or smacss, etc. While it may seem on-the-spot, it gives us an insight to how well they work outside their comfort zones and adapt to unfamiliar techs.
Our in-house developers are pragmatists over purists, while still being specialists in various techs. And we're fluid with our tech/tools and everyone is at least an expert in one of the current web techs.
And the best thing (imo) about my team is, everyone is excited about new tech. We always try to one-up each other in our various specializations, hence, are also aware of the limitations of our area-of-expertise.
Which comes in handy during interviews. If a candidate says they are an expert in css, we have a resident css expert that can put their claims to the test. You wouldn't believe how many failed candidates proclaim to be a css purist, only to fall short when it comes to organizing and scaling and documentation.
Being so functional and playing so nicely with typescript was the main reason I swayed to react rather than vuejs.
The whole ecosystem of state management does feel like a bit of a wild west.. but I guess that's often the feeling with javascript.
I ended up settling with easy-peasy, which I think has similar aims to zustand. Definitely appreciate that it uses immer out of the box as that seems like a very sensible default way to go.
That requires you to create 2 new components (which unlike React, will need to be in separate files if you're using SFCs) and pass down all the props another layer.
In the end, I got around it by implementing a "passthrough" component so that you can then do
Formatted properly, I don't really find the React example any harder to read.
Your Vue example puts v-for and v-if on the same element, which is confusing - which is evaluated first? (IIRC, the answer depends on which version of Vue you are using).
> it will be different depending of the dev who coded it, because there is no enforced patterns
That applies to the rest of your codebase too, though. It's up to your team to decide on patterns and enforce them through linting, code review, and automatic formatting.
Also, both of your examples are missing `key`, though React will warn you about it and Vue will not.
> Also, both of your examples are missing `key`, though React will warn you about it and Vue will not
Vue will warn when you're missing a key on the loop.
>That requires you to create 2 new components (which unlike React, will need to be in separate files if you're using SFCs)
Your components don't need to be in separate files even when using SFC's.
Given 'component' can be as simple as adding to any Vue Component or SFC (when adding it to parent component option):
Congrats, you are reinventing part of VueJS, in a non standard, untested, undocumented, less readable way. But wait, you need another lambda to pass arguments to foo() should it change. And another wrapper for stopPropagation. And so on, and so on.
And now you have to install and manage deps, import them, while your blob is still less readable because you have maps+lambda+&& to understand before even reaching what DOM element you are manipulating.
The premise of React is that composing primitives is better than having a high level tool to do the job: it's supposed to be more generic, more flexible, easier to learn.
In in my experience, it's true only in the case you don't have a well defined problem. But with frontend UI, we do. We know very well the problem to solve. Give me helpers. Give me wrappers. That's the only case where I welcome a DSL.
I don't want to have to think in functions and workflow in my template.
I've used both extensively. IMO, complex composition is sometimes easier in React but Vue wins in pretty much everything else. It's almost never in my way.
I'd say Vue is the much more powerful tool in the hands of a skilled developer
The hard things are exactly the same as React because you can use whatever render function you want.
JS itself is a single-threaded event loop and all view engines basically follow the same functional pattern of data-> render function -> output. Vue comes with an HTML parser to create that render function, React and others use a JSX parser, or you can write your own from raw javascript.
You can technically use any of them with any render function parser, but Vue starting with HTML by default and all the other niceties around reactivity make it a better fit.
I know it's just an example, but it's really straightforward: you create a component which accepts a boolean prop and, based on that, either outputs the default slot directly or a wrapper containing the default slot via a simple v-if.
If you wanted to get fancy, you could also accept a tag prop and v-bind all other $attrs on the container to make that a general purpose component.
After building 2 large projects with Livewire (using it just to sprinkle interactivity instead of going for Vue, not being a psycho and building an entire SPA with Livewire), I simply don’t like it. In most cases it would be quicker for me to use jQuery, and the response times would be quicker.
Although Livewire allows you to do that, and shows counters in its examples, for such things that shouldn't require communication with the backend (e.g. saving, or grabbing data from the DB), you are rather meant to use something like Alpine or petite-vue for lightweight JS manipulation than to make use of Livewire's feature for it to waste a roundabout request to the backend.
If you are reaching for Alpine or petite-vue I would consider jquery. The reason why people moved on from it "heavy dom changes" = "slow", "too messy in heavy js pages" is the reason to use it here. Lightweight pages + jquery = fast development, quick to load/render and tidy looking code.
I think the initial marketing/examples for Phoenix Liveview and the like really did a disservice here; when you ask the team always says that the live part should really just be replacing what would have been xhr requests in an SPA - where you need server-side data or functionality. For local interactivity they recommend Alpine but too many people have already seen the counters example and drawn their own conclusions (and even built entire applications this way).
It seems like if you are developing solely to meet "SEO friendly" criteria, you aren't exploring many alternative solutions.
Does all this framework tooling exist to just avoid inspecting a user agent and serving from a different upstream?
Having to maintain a large set of template files, with a dependency on a separate language or framework seems contrary to your premise that Vue is specifically better because it uses "HTML templates by default"
Never said I was. In fact that's just another nice benefit of traditional server-side frameworks rather than something you have to worry about implementing all over again.
Blazor specifically is the first non-JS component-based UI framework for the web with multiple modes that bridges backend and frontend as a single service without any impedance mismatch. It's an entirely new way to approach web UIs and interactivity without all the plumbing and frontend-to-backend-for-the-frontend-to-the-backend nonsense. Livewire is not quite as polished but shows how far you can go with tight integration on the JS side.
Vue templates are far worse than JSX. JSX/TSX is understood by tools so you get static typing, code completion, go-to-definition and all the other benefits of modern tooling.
Static typing alone is enough to rule out Vue in my opinion. I even went as far as writing a static type checker for Vue to work around it. It works by compiling the Vue template to a dummy Typescript function that only typechecks if your Vue types are correct.
That's just a tooling issue. HTML has been around for a long time, and plenty of tools provide typing. Also Vue supports typescript. Vue itself throws errors if the variables don't exist in your template.
However you can use JSX with Vue if you want. All JS libraries are fundamentally the same, and all templating boils to a single function with input->output. Vue just offers HTML instead of JSX by default and it's far more useful in many instances.
Vue 3 is written in typescript and comes with full definitions. The composition API is all regular functions. It doesn’t get better supported than that.
> Server side rendering with progressive enhancement is available in pretty much every major JS framework
But then you are forced to use Javascript on the server side instead of whatever language you are already using. That seems to be a pretty good reason for using Vue as a tool for "progressive enhancement" to me.
Then maybe look at https://lit.dev/ it might be perfect solution for you, stencil i've heard is also nice. Since its custom-elements you just add custom tags and they will self upgrade.
Lit elements looks nice and it's good to see first-class support for WebComponents. I'm just a bit concerned about having to write declarative HTML in JavaScript functions. Mixing declarative and imperative code can lead to some unwieldy templates so I prefer am approach with minimal templating enhancements sprinkled into standard HTML. What would be an approach, similar to Vue, to enforce the separation of imperative business frim declarative layout definitions using LitElement, Polymer, or similar WebComponents frameworks?
This is indeed addressing a similar scope to Alpine, but aims to be even more minimal.
petite-vue is less than half the size of Alpine.
petite-vue has no transition system (maybe this can be an opt-in plugin).
Alpine is developing its own ecosystem and likely will diverge more from Vue in the future. petite-vue aligns with standard Vue behavior whenever possible, so it's less friction moving to standard Vue if needed. It's intended to cover the progressive enhancement use case where standard Vue is less optimized for nowadays.
That could be the perfect solution for my Rails dev. Sprinkling views with Vue feels more natural and in line with Rails philosophy for me than the pseudo SPA approach of Stimulus. I hope it will gain traction in the community.
We initially wanted to use it as a super powered jQuery, then we ended up using Vue as an SPA for part of our app (certain route served a Vue spa to users), now we are going all into the Vue ecosystem for SPA.
I’m a fan of using Vue incrementally, but what you will find is that no editors I have found support Vue inside html templates well. When you use Vue as a jQuery replacement, it gives you some nicety, but it ends having pretty gnarly strings to put html inside of Vue components.
Vue team, if you can get editors to support your string template syntax, that would be killer. Even better, if there was a way to use single file components without the full build step (I.e. bundle up single file components the first time they are needed by a client) and inject that right into the html template that would be amazing.
Vue components are transpiled to JavaScript code when you build your app. Moving this step to client side makes your app take much longer to start. You also will need to ship the template compiler too, which is a few more kb.
Do you have an example of the problem you're describing? It sounds completely foreign to Vue to be honest, I've never encountered any issues with Vue inside HTML templates.
For only serving SFCs on request, you can use something like https://vitejs.dev/ during local dev, unless I'm misunderstanding, along with code-splitting.
According to petite-vue's readme, it supports the `v-cloak` directive [0], which is how vue recommends you hide the unprocessed template before it is mounted.
For more complicated logic, I think working with the @mounted event might work.
Anyway, looking at the docs, my approach wouldn't be as easy in vue-petite. It looks like Components have been functionally gutted. You can still approximate something, but you seem to lose a lot of ecosystem benefits of Vue. Theirs looks great for
Ultimately, this all seems like something coverage and tree-shaking should be able to do. If you're only using 5Kb of Vue, only 5Kb should be bundled. One day, eh? Until then, is the additional 25Kb actually hurting your users?