Congratulations to the Vue team, this is definitely a big win for them.
Reading through the RFC is really interesting. They specifically call out the dependency on Facebook as effectively being React's Single Point of Failure, citing their negative experiences with HHVM.
And for all of the love that people give React's big shifts (like hooks), the RFC specifically counts this against them, given that best practices have shifted so drastically in the last few years.
Although I understand what you saying about big shifts and kinda shared your opinion, specially about hooks, I started a new project from scratch last week and decided to give hooks a try (and, for reference, I've been using React on a daily basis for 5 years).
Oh boy I was wrong.
Hooks are way more easier and intuitive than what I thought. It makes code so much more readable and easier to reason about. Especially when before you had to wrap your components into x number of HOCs to inject the props your component needed, risking props collision, making it really hard to debug and use with TypeScript, and eventually making it a nightmare to understand and maintain your component. I'm not surprised that every React library added a hook API to its core.
At the end of the day it makes me more productive, so I guess that big shift was also a big win.
I've been through two large-scale projects now where we went 100% into hooks, and after a couple years the excitement has faded and I often wonder if it was worth it. It seems to end up making code even more complex than before, even though components look simpler on the surface. Not enough to go back to classes, but doesn't feel as good as those first steps. I absolutely hate the manual dependency tracking and having every single thing be wrapped in a useX() method to avoid unnecessary updates.
... having every single thing be wrapped in a useX() method to avoid unnecessary updates
That is a bit annoying, but it's significantly less annoying than having a single huge componentShouldUpdate function that deals with everything a complicated component uses.
Hooks don't really change the work a component does. The logic is essentially the same. They just break it down in to smaller, more reusable, more declarative units. That's usually nicer to work with and a lot more "React-y".
Is it really that bad? eslint-plugin-react-hooks installs by default when creating a project with create-react-app, which basically does the work for you.
In my opinion, the issue here is going 100%. There are use cases where having a class component is easier to manage, f.ex: if you make use of external classes.
Well-led projects tend to create new spin-offs rather than overextend their original idea. The former is riskier and more liable to fail, whereas the latter chases diminishing returns and undermines the conceptual integrity of the system.
Microsoft forcing Windows on mobile devices in the 2000s is an easy example of that kind of failed leadership.
I like hooks, but I've found them to be the biggest foot guns in my 20 year career.
Forget a dependency in the dependencies array, forget an useMemo or a useCallback and your application will rerender like crazy.
Yes, it looks nice from the point of view of understanding the code, but what actually happens at runtime and the amount of miss steps they can produce is astounding.
Nowadays I'm using Vue and it is way, way easier to deal with due to the reactivity model.
> you had to wrap your components into x number of HOCs to inject the props your component needed, risking props collision, making it really hard to debug...
What kind of application are you developing? Do you have complex UI? Or just lots and lots of pages where you reuse components a lot?
The kind of app that has 60k LOC, dozen of pages, makes 15 fetches per page (e.g. a report with 5 charts and 3 series per chart), reuse data between pages to avoid remaking the same fetches, have 1 or 2 forms synchronized between every page (like dates and selects filters), save the filters into the URL query params to be able to share the report and restore it when you open/refresh the app, and so on.
You end up with code like this at the bottom of your files
Although it's probably not that common anymore (as OC said, practices changed), it was a common pattern a few years ago.
In the new project I started last week, I'm using only hooks/context and a few libraries like react-router (useHistory, useParams), react-query (useQuery, useMutation), react-hooks-form (useForm)… and it has been a breath of fresh air. react-query is definitely another "big shift", it completely changed the way I used to think about fetching data and centralize it. It's very good, I highly recommend to try it.
Your example would be considerably simpler if you had separation of concerns [1]. You have routing, data fetching, redux, visual components, all in that small snippet. Sadly React devs seem to do this all the time... its like they have never heard of MVC.
I suggest searching what each of those HOCs is doing. This code is not dealing with routing, fetching, managing state or rendering. It is merely "gluing" those things together. Doing that can be considered a "single concern".
Over-splitting things only makes them worse to read and understand, even though each sub-component is prettier to look at.
Also notice there's a disclaimer on your linked article here the author retracts the recommendation.
> Over-splitting things only makes them worse to read and understand, even though each sub-component is prettier to look at.
React is a UI technology, and only your view layer should know about the React stack. The model layer should be UI-technology agnostic (includes avoiding Redux etc.) and so should most of the controller layer. If something better than React comes along (and it will) only the view layer should need to be rewritten.
Once again, I suggest that you search what each of those HOCs is doing.
These functions are not part of what would be a controller or model layer in MVC. This code is not dealing with routing, fetching, managing state or rendering. They are merely gluing complex data coming from these other parts of the system into what is the view layer here. The logical separation still exists!
Sure OP could reimplement all of them by hand, but ultimately it doesn't matter: the code is still properly separated in the way you're mentioning. Libraries like those are free to have functions operating in multiple concerns, as long as the logical separation still exists, which it does.
You are still wrong. This portion of the UI in this case doesn't care about the routing mechanism itself, but it does care about the history, which page is the current, and it also wants to trigger route navigations. This is a navigational component after all!
If your app needs to show, say, a menu bar, you need those things. Maybe some apps don't, but most of them do.
How would you implement this communication in your ideal system?
Let's see:
This component lives around two or three levels down from the entry point of your React tree (the part which communicates with the router). Which way is simplest way to connect this to the router indirectly? One way is by passing values and callbacks via props, from layer to layer, until it reaches the menubar. This works and is completely isolated, you basically have plain-simple-Javascript-objects "injected" from the top level, or instances of an interface, if you're doing Typescript! This follows the I of SOLID: Interface Segregation Principle. It also provides you with the S, Separation of Concerns.
But the "prop-drilling" is way too cumbersome. Let's maybe use the Context API, which is a way of replacing prop-drilling? It's still properly isolated.
Congratulations, you just re-invented the wheel and re-implemented exactly what withRouter does.
Sure you could have your own homegrown interfaces. Or maybe you could have no menu at all in your app! It's your choice. But it doesn't matter: this is still following the rules you are calling for.
The snippet illustrates exactly the concepts described in the article you linked.
And you are talking about MVC but that's kinda what is going on here: a bunch of smart components are injecting data ("model") and methods ("controller") into a dumb component ("view"), which displays them and calls them when some events are triggered (e.g. mount, change, clicks, submit, etc).
Yeah this is true, everyone doesn't like change in the beginning. but once I started using hooks for a couple of weeks, it is amazing to see that my productivity is increased a lot
I don't know. I'm not as familiar with Vue, but React's ecosystem is in such a good spot right now. Between things like RTKQ (or react-query), Material-UI, and react-hook-form, the abstractions over common web use-cases are just so terrific to work with nowadays.
And then just being the larger community, I just feel like all there's more examples in general for everything. Most things default to React as the guiding implementation.
I agree with that. Its been like a twilight zone interviewing for anything frontend in Silicon Valley the last couple years as they "me too" for React, while I use Vue on my own projects.
Now, the original reason I chose Vue was mostly around a small client side package size, but all the SPA frameworks have some version that prides itself in small client side package side now, and they mostly reach parity on similar concepts.
Facebook is a steward not a dependency. React has been free and open source and largely driven by the needs of the community. Right down to that time when the community cried out about Facebook's odd license clause regarding patents. And they changed it.
But I can't imagine modern technology being where it is without big shifts. Perhaps that is not good for very long term projects. We'll see how Vue fairs in the long run if they never make any big shifts, I suppose.
Then again, none of the big shifts in React broke anything permanently, did they? I could be wrong about this, I haven't been paying attention since the very beginning…
The WordPress group isn't part of the community? That it's a big org is a distinction you're making, not me. Open source communities are full of big organizations.
And now that the genie is out of the bottle anyone can do as they please with this fairly small rendering library and Facebook can't stop them. So I'm still not sure what the concern about Facebook is?
So, nothing more than ambiguous conjecture? Got it.
Well, I'm pretty happy using it and I certainly don't lose any sleep over Facebook having built it. Quite the opposite - I thank them for it! Nobody can take away my rights to freely available MIT licensed code.
> We'll see how Vue fairs in the long run if they never make any big shifts, I suppose.
Vue 2 to Vue 3 has felt like a big shift. Big enough to leave most libraries incompatible with Vue3 and a lot of community forks spread around while library authors work out how (and if) to support both versions.
Vue 3 is an improvement to work with IMO but it's a rewrite your code kind of upgrade.
Angularjs didn’t really stick around after google moved on to angular 2, despite being open source. People who still wanted a similar workflow switched to vue. I think that’s the concern
There's plenty of angularjs still around, for projects that can't or don't want to move to angular 2. The official end-of-life keeps getting pushed back, and I won't be surprised if someone r eventually forks it.
I feel like I'm in an alien world when it comes to Vue - it has this weird pattern of making strings do loads of heavy lifting.
The Github Commits[1] example on their documentation has a load of stuff that just doesn't sit right with me.
Things like
v-for="record in commits"
to loop over something is insane to me - this isn't code, this is a string inside a html attribute! How can you get any sort of good type analysis/variable checking/syntax highlighting inside this?
Similarly, accessing properties like
:href="record.html_url"
has the exact same issues - what if there's a typo here? My IDE can't highlight that this is wrong because it's *not code* and is just a string.
Maybe I'm just the odd one out here, but vue (and angular) love to use strings as a makeshift programming language, which to me is a major smell.
> My IDE can't highlight that this is wrong because it's not code and is just a string
Code is just a string too, treating the 'code' inside the string literals after the v-for is just an extra level of syntax handling - The IDE I use (Intellij) can handle it just fine.
Yeah, this isn't really an issue; it's just a templating language. You can get an extension for your IDE to make it syntax highlight correctly. That's like saying a .js file is just a string. Um, yes I guess sure? All code is just a string. HTML is also just a string. Vue's HTML templating syntax is also just a string, but it's also code. It's code that's mainly HTML, with certain spots that allow full JavaScript. And just like normal code, you can have compile time errors, syntax errors, runtime errors, etc.
Also as a side note: I'd say the best thing about Vue isn't it's templating system, but the fact that it's truly reactive. In react, only rendering is truly reactive. If you have reactive variables that depend on each other, then you have to manually mark those dependencies. Vue can deduce that dependency graph automatically, which makes coding much easier. It's like a giant spreadsheet.
This is exactly the point of vue. On the surface, it looks a lot like a cleaner angularjs, but it's very different. There's no need for a digest cycle to re-evaluate watch expressions on each iteration, because it uses getters and setters to detect changes (though it still supports watchers too). Vue is also very different from React, which (when I last used it) required components to implement shouldComponentUpdate. Vue does this at the cost of breaking compatibility with older browsers (which were not old at all when React and Angular 1.0 came out); I think the tradeoff is worth it.
Vue is brilliant when you actually use it. Nothing you've mentioned is remotely ever a problem in my experience. Also :href="xxx" isn't a string, that is javascript in there.
You won't ever have more than 10 characters at most in an attribute, and if you do you make a method for it and call the method.
The other alternative is JSX type stuff in react where you are injecting full JS into the templates which is like committing seppuku to me. Vue is so much nicer to use than react IMO, and I've used both extensively.
> :href="xxx" isn't a string, that is javascript in there.
This is the part I don't really follow, though. Technically:
<a href="print(1//3)"></a>
href here isn't a string, it's python, but it's stored as a string, representing python. In the :href example for JS, that's not JS - an engine isn't seeing that - that's a string that is evaluated as JS at some point in the vue lifecycle.
Without refreshing my knowledge on it, I don't think it's actually a string. A <template> block is actually a "single file component" which is a special vue plugin/loader/whatever for webpack. It compiles template/script/style tags into a single compiled version.
I'm like 60% sure that your "string' example is never run in production. So I believe that it gets compiled before vue even sees it (at build time, or dev-server compile time) into the standard method that vue is used to... a vue component:
I think it won't really make sense until you try the alternatives. I've used react since it's inception, vue, ember, angular (going back all the way to angular 1), knockout, etc etc etc.
All these frameworks try to solve what you're mentioning in different ways.
Obviously people have different opinions, but after seeing the way things are done from all these different frameworks, Vue is extremely "clean" and minimal feeling, while remaining extremely flexible. I have built multiple very complicated apps and there's nothing that I'm not absolutely DELIGHTED how it's solved, especially with the new composition API. It feels extremely elegant compared to the other ones I've mentioned.
Perhaps consider the alternatives, and you most certainly will have a much worse development experience if you're not willing to play ball with 2-way data binding (ie use html attributes to bind things, etc). As I said, other frameworks have tried other methods to minimize attribute use and they're excruciating to use. Ember is literally one of the most painful frameworks I've ever used to do even the most simple of things.
Vue template HTML can be parsed by an HTML parser - lots of them available. Can you do that with JSX ? Personally, I find JSX is more of an "alien" than Vue template HTML.
All code is text. There is no pure "code" representation, text inside attributes being parsed as JS is no different than parsing text inside some <script> tags.
Also modern component-based JS frameworks all work the same way. The UI definition is a template that's compiled into a render function which produces the final output during runtime. Each framework uses different syntax: React uses JSX which is a domain specific language (DSL) that mixes HTMl-like tags into Javascript. Vue uses HTML with directives on top. Angular, Svelte, etc all use their own formats.
You can even mix and match (use JSX with Vue) or write your own render function if you want, but it's the same text->parsing->lexing->compilation cycle that every language goes through before turning into actual CPU instructions.
> text inside attributes being parsed as JS is no different than parsing text inside some <script> tags.
It is different. Because "text inside script tags" is Javascript. Vue's templating syntax is a weird and inconsistent mishmash of custom DSL, Javascript subsets and Javascript expressions.
Text inside script tags is parsed as JavaScript by default. It can be other languages too, like typescript inside a .Vue file.
Again, it’s all just text in different syntax. Programming languages are just a very large and well defined syntax compared to a template language, but that’s all it is.
Vue’s directives offer just enough control to handle 99% of scenarios while remaining within HTML.
> Text inside script tags is parsed as JavaScript by default. It can be other languages too
It can be, but usually isn't.
> Again, it’s all just text in different syntax.
Again, it's not. And the reason is simple: the browser literally knows nothing about other syntaxes but Javascript [1]
So, no, "text in Vue" is literally not the same as "text in script tags". It is a mish-mash of:
- Vue's own DSL (see v-for)
- JS expressions that are wrapped in some scope (see v-if)
- JS-like DSL where function cals are not function calls, there are magic vars, but objects are also fine (see v-on)
- Maybe JS expressions in v-bind? But depends on the attribute name? Can use string concatenation, but anything else?
- Actual JS expressions in {{}} which can't be used just anywhere... but then these expressions can have pipes into filters in them? And filters once again are JS-like, but are not
None of this has any coherent specification, and we rely on Vue to properly parse and break it down into actual Javascript code that can then be included in a <script> tag.
Edit: I had the same laundry list of things for Svelte before Svelte 2, but Svelte 3 is significantly more consistent and coherent in what it expects in a template.
[1] There are ways to make it know other syntaxes, but that is rare and has largely fallen out of favor.
The point is that all code starts as simple text, and is parsed and compiled into some lower layer until it finally gets to machine code. What actually does the compilation is irrelevant.
All of these JS frameworks (React+JSX, Vue+HTML, Angular, Svelte, etc) require template compilation into an actual JS render function before a browser ever runs it, but compilation is the same fundamental process regardless of language or environment: https://en.wikipedia.org/wiki/Compiler
So yes it's all just text following a different syntax, and Vue's documentation already describes exactly what you can run: https://v3.vuejs.org/api/directives.html
> The point is that all code starts as simple text, and is parsed and compiled into some lower layer
Yup
> What actually does the compilation is irrelevant.
Nope. It is relevant. For the stuff you put between script tags there's at the very least https://github.com/tc39/ecma262 that you can look at and tell exactly what's going on with your code.
With Vue (and, yes, React and Svelte and Angular): who knows? It might very well evalueate strings at runtime for all we know.
> All of these JS frameworks (React+JSX, Vue+HTML, Angular, Svelte, etc) require template compilation into an actual JS render function before a browser ever runs it,
Yup. It's an additional, different step before it can even get to the browser. The problem with this step is that for most of this code there's not even a coherent specification of what it is, and how it's compiled.
> and Vue's documentation already describes exactly what you can run
It really doesn't. For example, here's the "documentation" on v-for:
Expects: Array | Object | number | string | Iterable
Expects where? Is this correct:
<div v-for="{ a: 1, b: 2 }"></div>
Answer: no. Because the actual description of what is expected is written in examples. Same goes for every single other directive. I mean, v-bind expects "any (with argument)" (what does this even mean?) and v-if expects "any", and both of these are false statements.
The topic is that all code is text, and everything can be parsed and understood based on specific language grammars, even if they're embedded within each other.
What are you even arguing at this point? This isn't about compilation or strings anymore. You don't like Vue's specific DSL? Or you don't understand it? Or you found a problem with the documentation? Or do you need a full grammar and syntax definition before you can do anything?
That Vue isn't "the same as text between script tags". Because "text between script tags" is fully specified, and known to the browser.
Vue's ad-hoc mish-mash of DSLs has to go through an unspecified series of transformations before it can even become a "text between script tags". And that's the issue not just with Vue, but with any other templating layers.
> but you can always solve your mystery of "who knows" by just looking at the source code
Ah yes. The good old "code is the source of truth" fallacy. Can you point to me where exactly in code it specifies this: `Expects: Array | Object | number | string | Iterable (since 2.6)`?
Yes, Vue directives aren't JS. It's a separate DSL. The whole point is that it is a syntax that can be parsed, compiled and understood rather than just "strings".
I'm not sure why you're stuck on this. Templates are just a more simplistic programming language. That's how so many IDEs can still provide help with them.
The only difference in Vue is not having to explicitly declare the variable. But so what?
You said "strings are magic and not code" to which I said "all code is text so there are no magic strings". Now you and the other poster keep saying "well this string isn't the same syntax as JS" but I don't see what the point is. Why does it have to be valid JS?
Again, you can embed syntax within each other just fine. JSX has HTML tags inside JS. HTML has tags like <style> and <script> for other languages (regardless of what the default language is or what parses it).
So, for the last time, what's the actual argument?
> How is it invalid? Here's the syntax about a for..in loop
for (variable in object) {
statement
}
And here's the syntax for Vue's for..in loop. Only one of it is somewhat Javascript:
item in items
(item, index) in items
(val, key) in object
(val, name, index) in object
And, of course, there's an extension to that
v-for="item in items" :key="item.id"
Edit: additionally, from that very link: "for...in should not be used to iterate over an Array where the index order is important." But this doesn't concern Vue, it maintains the order in its for..in.
It does exactly what I think it does, which is either iterate over the properties if it's an object or the elements if it's an array. This is true for Vue and Javascript. I suggest you read the documentation I linked earlier.
Also Vue's directives are not JS. It's a separate DSL. I've repeated this enough so I'll end this discussion here.
In Javascript, `for..in` prints the keys. In an object, the keys are the properties. In an array, the keys are the indexes. If you want the values then use the key to lookup the value from the object or array.
Either way it's entirely consistent: an iterator that works on both objects and arrays and prints the keys without guaranteeing order. Does that clear up the confusion?
If it's a template then it's a very complex one, and under closer inspection it reads almost like storing code in a string and evalling it.
Let's say we want to iterate over commits in reverse. A google shows that we can do something like this:
v-for="item in items | orderBy 'field' -1"
So, there's pipes now, and Vue has essentially re-invented a programming language inside HTML attributes. But then comes this example below it:
v-for="item in _.reverse(items)"
And this line is terrifying! If this string is able to use lodash, then that means it's able to access the JS global scope, and therefore is very powerful - yet the resulting template is nonsense js, but still at some point involves JS evaluation?
Maybe I'm missing something though - I don't use Vue and if something is this big with this approach, I'm definitely missing something.
EDIT: A search for *new Function(` calls in the vue github repository shows quite a lot of code that essentially evals strings.
I don't know if you haven't had much experience with templating engines, but having the ability to write programmatic expressions to make a layout dynamic is a basic necessity that pretty much every known templating engine has. "It reads like storing code in a string and evalling it" sounds very funny in this context because that's exactly what every solution does and it works pretty well in practice.
My issue isn't the existance of programmatic expressions (yeah, it's the point of templating languages), but more that the way vue (and angular) do it is a mess of syntaxes that creates a really, really strange template.
The lodash example is the main critique because that is not JS, but it involves evaluating JS - it's created its own programming language with its own rules -- when one was right there from the beginning!
Like any templating engine there's always just enough power given to have the ability to write something stupid or complex in the template. Again not really a problem in practice.
The scary underscore expression you're referring to can easily just be written as a reversedList variable in "normal" JS and get referenced plainly in the template. So the template expression syntax never has to be as messy as you might think it is.
The "scary underscore" expression isn't scary because it's an underscore, it's because it implies the evaluation of JS, such that you could (and obviously wouldn't) do things like
v-for="x in console.log('hello world!') && fetch('/') && [1,2]"
(my syntax might be off since I don't use Vue, but the merit should still apply)
My point is that when your templating language starts doing things like this (and inevitably, all of them do) - you've created a new programming language that is generally less thought out as one than deliberately made programming languages. Although the above for loop is evaluating JS, the syntax is decidedly not JS.
> "It reads like storing code in a string and evalling it" sounds very funny in this context because that's exactly what every solution does.
Its not, though. JSX-based solutions (not just React, but Solid and others) don't (actually, neither do many frameworks with more traditional-looking templates, including, AIUI, Vue, actually compile templates to render functions, so it just looks like old school “string with embedded code which is evalled” ttemplates)
I know it's pedantic but this is still JavaScript we're talking about not binary so the "compiled render function" is still ultimately just "a string that gets evaled".
In any case the implementation details aren't important it's what it appears to be that is apparently the problem.
> it's what it appears to be that is apparently the problem.
Yep, Someone mentioned in another part of this thread that Vue compiles most of this out before production, so my remaning confusion pretty much stems from the DSL being a mishmash of html attribute context, vue custom syntax, and evaluated JS.
Templating is the wrong approach. Component-based approaches where you use polymorphism rather than putting logic in your templates are much better. Look at Wicket for a HTML UI framework done right, IMO.
People like templates, and the clear and declarative correspondence between input and output.
You can write React without using JSX, and I assume Vue without templates, but unless the components system has a declarative layer so thin it might as well be templates (e.g. elm, or clojure’s hiccup) and it is entirely expression based, they’ll want templates.
Wicket looks like absolute nonsense of the worst kind. It completely reminds me of Struts and Spring and friends, and that is not a positive comparison.
> People like templates, and the clear and declarative correspondence between input and output.
You don't get that clear correspondence if you can have logic in your templates, and even supposedly simple expression languages in templates somehow always end up growing ifs, looping constructs and so on. Plain HTML fragments are good, but they need to be kept absolutely simple.
> Wicket looks like absolute nonsense of the worst kind. It completely reminds me of Struts and Spring and friends, and that is not a positive comparison.
I don't understand your position at all. The problems of Struts and Spring are the problems of templates only more so - if I were to make a spectrum I'd have Struts (and Tapestry) at one end, Wicket (and hiccup) at the other, and traditional templates somewhere in the middle.
> You don't get that clear correspondence if you can have logic in your templates
You absolutely do.
> I don't understand your position at all. The problems of Struts and Spring are the problems of templates only more so - if I were to make a spectrum I'd have Struts (and Tapestry) at one end, Wicket (and hiccup) at the other, and traditional templates somewhere in the middle.
The struts I got to use was full of "smart JSP custom tags" because "components are the right way" and subclasses all the things, it looked exactly like the examples I see of Wicket: keep bouncing through layers and files of useless nonsense because all the logic has to be out of the markup but all of the markup has to be out of the code, and formatting a list takes you through 3 templates and 5 classes.
> Wicket (and hiccup) at the other, and traditional templates somewhere in the middle.
That makes no sense whatsoever. Wicket and hiccup have nothing in common.
> The struts I got to use was full of "smart JSP custom tags"
Which is very much the opposite of how Wicket does things: there are no custom tags, the templates are inert HTML and there's a very small, non-customizable set of wicket tags/attributes (IMO the right way to do it is just IDs).
> That makes no sense whatsoever. Wicket and hiccup have nothing in common.
What they have in common is that all your logic is in code, not markup.
I feel like you're getting hung-up on the fact that the template directive is also a valid attribute and not something similar to jinja - but that's just syntax
This has been the debate of templating systems for as long as I can remember. Do you want your looping construct to use the same syntax as your markup language (so all the tools you use that operate on the markup "just work", without any modifications)? Or do you want to use the same looping constructs as the language you are programming in (so there's no need to invent or learn a DSL built on top of a markup language)?
Both approaches are valid, and each comes with its own set of tradeoffs.
Yeah well, its not really HTML - its JSX and it reads quite differently. Most folks who create HTML prefer to read HTML not Reacts domain language. HTML is a documented world-wide standard implemented by web-browsers. JSX is not.
You are trying to discuss things you have never tried in practice, just saw some examples in the docs. Your opponents are trying to explain this fact politely.
Many users - who weren't programmers by training - loved CF for the ease of understanding. They had a DX paradigm that worked and I understand why people try to emulate it. It's a question of audience, and not for the HN crowd.
Except that SPA frameworks are designed to complicate things, not to make them easier to understand. And SPA framework developers are crazy expensive, mor expensive than seasoned C++ systems programmers. (The two facts are probably linked.)
Have you ever developed a complicated front-end system? Not using a vue/react style framework would be ludicrous (ie, building something like Facebook Ads UI or Google Analytics UI). I find it super bizarre you say "complicate things" when they do 100% the opposite. I would love to understand what you would use if you were tasked with building FB Ads manager interface: https://disruptiveadvertising.com/static/61a4440576bffd6e6a2...
> I find it super bizarre you say "complicate things" when they do 100% the opposite.
They're way, way overengineered for the very limited use cases they're designed for.
If you're going to ditch the browser API's and re-write the world in Javascript, why not take into consideration all of the history of GUI development and do it right? I.e., make a real layout engine, proper widget hierarchies, real encapsulation, etc.
Instead there's some sort of frankenstein in-between state where you've ditched all the benefits of native browser API's but haven't arrived anywhere that's a true paradigm shift.
TL;DR - yeah, they make some things easier to reason about, but for any sort of non-standard webapp you'll still need to write an equivalent mountain of hacks and framework adaptors.
"very limited uses" mmmmm what? Reactive frameworks are one of the widest used front-end design patterns.
You answered my questions with a bunch of theoretical non-answers that comes off like a tech purist who hasn't actually used the technologies but has a lot of opinions about them. Do you have a lot of experience designing non-trivial/complicated web apps with very heavy front-end features? "layout engine", "widget hierarchies" what _exactly_ does that mean in the context of designing something as complicated as Google Analytics/FB Biz Manager using javascript. If you are proposing not using primarily JS logic but rather server logic, or not as a SPA (or isometric hybrid like nuxt/next), then that makes me want to hear your answer even more.
I'd clap harder if Vue weren't so desperate to become React and focus on their own strengths. React certainly appealed to a lot of devs who at best disliked working with HTML & CSS, but Vue welcomed everyone with an excellent gentle slope to gently move devs away from direct Dom manipulation and embrace reactive paradigms. Folks with small shops could now refactor their codebases with relative ease.
If only the Vue team could understand, we don't want React features. We'll use React when we want them. We want Vuejs.
I tried React during its early years, and switched to Vue.
It's just a little bit more coherent platform than React. There are core Vue projects, and they go in lockstep with Vue releases.
Second, Vue understood how fragile, and the same time important tooling is. There are many very mature Vue packages to scaffold, and manage your Webpack, or other build system setup for you. This saves a lot of hours because if this setup fails on you, it will also fail on tens of thousands other developers, and will get fixed quickly.
Vue itself been less tooling dependent at the start, and it played a role it its early popularity, vs React, which was superglued to Webpack or something similar from the start. Now, the situation has reversed I think, and it is a pain point.
I think there is a good sense of direction with Vue, with Evan being better at keeping focus on objectives for the next release than a lot of other frameworks developed by companies. I had few silent breakages during updating projects to new version.
Lastly, Evan is a very decent person, and this helps the project getting more contributors.
Vetur languished for years without the resources it needed. From lack-luster type recognition to bugs that would just crush its performance. I believe it has just recently(within the past year or so) been taken up a level.
TSX support, and frankly JSX is the future of VueJS IMHO, also only really started working well with the addition of attribute namespaces to TypeScript.
So while these things have improved recently I would say language tooling has been really lackluster compared to the React ecosystem even 4+ years ago..
Vue still has the same progressive-enhancement low-tooling approach as before. It's only broadened in its ability to be used in more complex environments with full toolchains but you can just add a <script> tag and start coding.
I do agree that Vue 3 was rather badly released though, as everything from the websites and docs to the plugins and devtools were all at different stages.
Just curious, but in your opinion, how does the composition API improve on React hooks?
I used Vue 2 for some projects a year or two ago, and recently have been comparing React hooks & Vue's composition API. Composition is definitely better than mixins, but as a new React user, hooks are feeling more intuitive right off the bat. With Vue 3, I feel like I have to decide for every component whether to stick with the options API or use the setup method, or end up with some awkward in-between.
I was always a big fan of Vue though; I'd appreciate any insight you can give on the Vue 3 additions.
> Just curious, but in your opinion, how does the composition API improve on React hooks?
I'm a fan of how Vue's composition API executes exactly once during a component lifetime (during `setup()`), whereas React hooks get set up again on every render. I find it I find Vue's approach easier to mentally model, and thus easier to write correct code (especially when doing something complicated where state changes / effect executions trigger each other). Since `setup()` is only run once, I can also do things like store non-reactive state in closure variables without wrapping those variables in hooks.
I think this puts it in perspective more; if I understand what you're saying correctly, then setup essentially gives you more fine-grained control over Vue's reactivity system, as opposed to just doing it all for you when a component is created. Which allows you to more easily pull out & consolidate reusable logic as needed.
It is kinda nice making reactive state really explicit like that; I like Svelte's approach for similar reasons.
THIS. People focus so much on templates vs jsx and most forget this is the biggest difference, and a very important one. I think people discarding Vue because they don't like templates just don't understand this difference.
Agreed, Svelte is by far the most productive FE I’ve used. Coming from a jQuery/templating background, at first felt Vue was the most intuitive to use (React felt alien, Angular overly verbose)…
Until I met Svelte…Vue, minus the BS. A clean template system, less boilerplate, no Virtual DOM, nice Typescript support, intuitive state mgmt.
Btw if you liked Polymer 2.0/3.0 you may also like Lit (formerly lit-element)[0].
It has a less "proven" ecosystem around state/async action management and some other concerns (i.e. there's no redux/vuex), but the controller paradigm[1] looks pretty fresh and interesting. I'm of the belief that most of the time doing an async request or two and some caching and good architecture is enough for most app (not everyone needs the flux pattern).
Lit is by the best implementation and standards-compliant component-centric library IMO. Tried a bunch of them back when I was trying to figure out if there's a better way to handle state in a component-centric world[3].
Am I the only one who still has a preference for vanilla js?
Maybe it’s just my use cases, but every time I try to use a high level framework like vue or react I am immediately bogged down by unnecessary abstraction and complexity.
Again, I’m no UI dev so please correct me if I’m wrong! I have pretty simple needs for web app UI usually…I’m not trying to build Facebook. Why do I need react/vue/whatever?
Have you tried Vue? It’s very different than React because you can just augment your HTML with what you need, it’s not all or nothing. What’s complex and usually overkill for small projects is the "modern" build tool chain, but you can ignore that and just add the <script src> and be done with it (same with React BTW). You can get familiar with AlpineJS which is kind of a minimalist Vue.
That’s for the tips! I’ll take a look at alpineJS. I tried vue a long time ago but would definitely give it another look. My complaints really come from using react and I assumed vue had similar issues
Working without a framework in a team, you can easily have a situation where each developer comes up with novel solutions to various basic and essentially common problems. I've seen it happen that each dev invents their own way of working, their own micro-framework, and the others are mostly unable to work productively in the others' particular styles.
This can of course be countered by pair work, extensive reviews, creating best practices, etc. However, there's a value in adopting something that already comes with those, instead of inventing them from scratch. The correct answer really depends on your situation and team size, I guess.
2. make your own abstractions, utilities, structures etc
No comment on 1.
On 2. I know you think your code is so elegant and blows people' mind away or whatever, but trust me, give it to someone else to have a read. They'd probably disagree with you more than they would ever disagree with a framework.
At least the frameworks have tests and documents for their functions
The only UIs I create are pretty simple. For simple interfaces I would much rather deal with spaghetti and homegrown solutions rather than massive overhead and complicated abstractions.
A lot of people just blindly build everything they write with their framework of choice. I argue that react is overkill for 9/10 web apps.
Honestly if you just pay attention to the constantly shifting fads and “best practices” you’d have noticed by now.
Example: object oriented programming was THE WAY the write code a few years ago. Now functional programming is all the rage even though it has existed for decades. In fact, idiomatic react code just recently made the same switch.
I think it’s important to think critically and frankly having a discussion about the efficacy of contemporary design choices is the starting point.
I agree with that, but what you advocade isn't efficacy, "just write good vanilla js" is as useful of a statement as "just write clean code".
In practice I've never seen anyone capable of writing clean vanilla js except for myself.
Of course that's just me jerking off to my own standard. "Vanilla" is an useless approach when it comes to finding a common ground to work in a professional context. It's in-efficacy in that sense.
You don't if your User Interfaces are basic. But for web applications theses frameworks with the ability to quickly define your own web components are incredibly useful. It can still be frustrating sometimes, but when the app gets more complex, doing this without a web framework is probably insanity.
BTW, Vue 3.0 uses Typescript, but you can still programm with plain Javascript. That it what I am doing (I may be part of a minority).
I'm somewhat in agreement with you. My experience was vanilla js first, then jquery, then angularjs. When I first used angularjs I was annoyed by having to learn about providers and services and factories and an alien templating system. But for all its questionable design decisions, it does provide one very significant benefit: composability.
Jquery had wonderful composability through its plugin system. If I want a tree widget, I just go to the jquery website and find one. (And of course you can do the same thing with vanilla js, but where are you going to go to find a tree widget if you don't want to build one yourself?)
The problem with jquery was that the "glue" was procedural javascript. That made it very difficult to use it from an html editor. With newer frameworks, the templating system is the glue. Where angular/react/vue/others differ is what that glue looks like.
So yeah, you can do all the same stuff with vanilla js that you can do with a framework, but you lose composability of widgets out of the box, and if you have composability, then you've just built a framework.
Huh. They're still deciding on whether to use Vue 2 or Vue 3... To me that's a definitive sign that Vue chasing after React's insane hooks system was a bad idea. I hope they figure out how to heal the rift before it's too late before we get another Python 2/3 situation.
A solid choice and well reasoned. It was a joy to read all of the discussions.
Been following Vue and Evan’s work since 2015, before it even reached 1.0. I think it strikes a good balance between the freedom of React and the rigidity if Angular. (Interpret the terms “freedom” and “rigidity” as you please.)
My only problem with Vue 2.x was the bad TS support, but I trust 3.x solves that.
In my experience, React is very particular at how you present your view logic. For state management, though, it has very few opinions and that freedom can be paralyzing. Do you use Redux? Do you just use built-in component state and props? Do you use the Hooks API? React solves one slice of problems in front-end development, but has few opinions outside of the view layer.
I stopped using it a while ago (2-3 years). I had central state management, and a few other bells and whistles.
I was the "go to" guy for when React didn't want to do something.
Most of my wrestling came in the form of:
- recycling html-elements
- "tweening" state. a friggin nightmare to have inbetween states
- performant animation stuff
- stateless node-to-node communication for stuff that would have not fit well in state
- keyboard navigation (think game ui)
Ugh. The more I learned about how it actually works, the more I came to hate it. And it kills me to see so many people who love it... like I'm an alien amongst the people (developers) who I once felt understood me.
React does not seem like a good fit for doing any of these things. Aside from keyboard navigation, which works just fine as far as I’ve seen.
I dunno, every time I see someone hating React they’ve been kind of stuck in doing things the jQuery way, and their components become this horrible frankenstein of modifying HTML both through React and directly.
Keyboard navigations as in up/left/right/down jumps around somewhat haphazardly placed items. Not tab/shift-tab accessibility.
And you are right that React is not a good fit for these things. That's why I say it's very limiting.
Also, for what it's worth, you might be mistaking "the jquery way" with "the vanilla way." As in:
- working with HTMLElements
- vs working with a superset (tsx) of a superset (ts) of javascript meant to look like html (sometimes), that creates js components that then create html that is then diffed with last html and finally applied to the appropriate innerHTML (and don't forget about all the hooks!).
Yeah, React is a pain for when you need to interact with the DOM elements themselves. If you want to add some logic based on where the element happens to be placed, instead of where you have told React to place your element, you're in for a headache. Now the DOM is one source of state (positioning) and your store (Redux or otherwise) is no longer the single source of truth.
IMO, there's no way it lasts purely because of this.
We already have the DOM, and there's literally nothing that React can do that requires its complexity EXCEPT server side rendering. Which most people never use.
> their components become this horrible frankenstein of modifying HTML both through React and directly.
I need to know what the problem is with modifying HTML inside a browser that knows and expects the HTML to be modified, even providing DOM APIs for this exact reason. What is the benefit of modifying a not the DOM besides the dubious claim of performace++?
I use react everyday now BTW. I needed to do something trivial like use something similar to setproperty to update CSS variable with JS returned values. This was part of a component that gets 3 colors and returns an array of RGB values which I need to change the background into a gradient. The one piece of advice I got from the internet is...
styled components.
FfS.
React is breaking every best practice from ~20 years ago of keeping concerns seperate. Sure Jqeury wasnt perfect but I could get a junior dev fresh out of school up an running in two weeks flat. There was no need to bend the time-space continuum with the black whole density of node_modules for every_single_thing.
Nothing at all. I've been using a custom made framework for 3 years that does everything React does and more. I could write the whole thing in a weekend. It's not hard, you just cache some functions that create HTML Elements, keep track of what state variables are used inside those functions, and rerender whenever those variables change.
React was a dumb idea from the very beginning, and anyone who knew vanilla js well could tell you that.
By tweening and animation, you mean shifting an element from one part of the screen to another? What part of react fights against this? I’ve been using react for 3 weeks and I’m just curious what I might run into later on
If you're animating using just css classes (or transitions), you'll be fine.
Some animations need to be run in javascript though, and doing that through state is a bad idea. You can use ref, and sometimes that's fine, but if the data is changing (hitting a moving target), then you need communication. Think coach-marks and scrolling at the same time.
And "tweening" views means showing the last view fade out while the next one fades in (or scrolls in, etc). This means displaying an old state, and a new state at the same time. The trick is to recycle your html elements, but it'll fight you for it.
> The trick is to recycle your html elements, but it'll fight you for it.
No, the trick is not to use React for animations in the first place.
It's simply not a good a idea to use regular React state for very short-lived data (like animation state) as React will end up re-rendering everything all the time, leading to a significant performance penalty. Instead, I would rather decouple the animated DOM elements from React's state & change handling and just use e.g. d3 to control them. (Yes, it's not pretty but animations have never been pretty in the first place.)
Speaking of (not) using React for short-lived data, this reminds me of another common pitfall: Forms. Many tutorials online blindly recommend binding every HTML input's value to a React state variable using onChange, usually causing the entire form to get re-rendered upon every single key press(!) No wonder the Web is so slow these days…
I really enjoyed working with Vue 2 until I started using TypeScript.
Vuex, the goto state manager just wasn't built for it (I ended up using vuex-module-decorators). Type safe templates were only partially possible with Vetur (vs code extension) but it was slow and resource hungry. I'm sure in Vue 3 this is much better now, but while evaluating to migrate to v3 this wasn't the case.
I became interested in React, because I was looking for a way to generate type safe email templates. Started using .tsx files with a library called typed-html and loved it so much that I end up migrating to React (now rendering email templates with ReactDOMServer.renderToString(element).
Still miss Vue's simplicity at times but having rock solid TypeScript support is something I value more.
I'm curious how Pinia works. I actually use MobX with VueJS and the way it has to hack itself into VueJS is a bit of a shame. I wish there would have been a more official integration point for third party reactive libraries.
For anyone alarmed about moving towards a SPA, and potential performance impacts etc, read the comments towards the top of this link from the Vue Team Lead and proposal co-author. They address the most obvious concerns.
Thanks for the link. A lot of people went out of their way to criticise Vue which makes me wonder how the general opinion of Vue has changed in the last year.
Over more than a decade I have gone through Adobe Flex, jquery, vanilla js, angular 1 & 2, vue 1 & 2, React, a bit of svelte, web components, my own custom state mgmt libraries.
The fundamental idea behind most modern FE frameworks remain the same. View is a function of state. The hardest problems in FE are state management and CSS/dom layout.
So as long as someone knows what they are doing any of the modern frameworks do a decent job. I have seen bad code in every framework.
So if the Wikipedia team knows Vue very well and yield its powers, may the force be with them.
Use the framework your team knows best. It’s really about the players more than the instrument.
I personally like React. It solves many of the pain points I’ve experienced over 10+ years. I’ve invested a lot of time learning it in depth. If someone told me to write react from scratch with hooks api, I know how to do it.
Seems Wikipedia chose Vue because folks knew Vue in depth. That’s a good way to move forward.
> Svelte, Inferno, and Preact are aggressively optimized for performance but have much smaller communities of users (Preact suffers from this issue to a lesser extent, but only as long as it maintains a very high level of compatibility with mainstream React, which may not be the case forever).
It was a hulking, omakase, MVC? based framework at a time when the oppo was Angular 2.0 & Backbone.js and people still used Bower, then React threw everything on its head in favor of component libraries while NPM came into the mix.
They eventually refactored in components and I think repackaged everything for the new js fe ecosystem, but the battle was already lost.
Picking Svelte is risky, given its low adoption. I'm not saying Svelte won't ever be widely adopted, but there's a risk that it fades away and you're stuck using a dead framework.
Svelte and Vue are actually very similar in some ways. Personally, I hope Vue creates an option to compile its components into static components like svelte; having the option to have a runtime component or a static compile time component would be super powerful!
react is api stable, but not api stable if you know what I mean. with react, the ground is always shifting underneath you, which something like wikimedia probably don't have the resources to keep up with. even, as someone who has done react professionally, I can advise any small nimble teams, out there react ain't for ya. it don't love ya. however, for the big enterprisey apps, yeah react is good.
For the big enterprise apps “the ground is always shifting underneath you” is the worst nightmare that can be imagined. The only exception is if your corporation controls these shifts.
- facebook used to maintain CSSTransition for animation but dropped support for it and gave it to a dude who broke not only the public API but also some features I was relying on. I'm left having to recreate all the animation in a different lib, meh
- lifecycles related deprecation: componentWillMount, componentWillReceiveProps, componentWillUpdate. My app used to have a lot of these but that's the easy part to migrate, the problem comes when third party libraries use those and nobody support those anymore
- method deprecation which brake third party libraries: findDOMNode. The 2 one I've used that relied on it: dnd and csstransition. There's no clear path forward that would take less than a few days to migrate my code, meh
- upgrading webpack to whatever your config should look like in 2021 and what new plugin for x is named
Nothing very specific to react in particular but for simple use case jquery or plain javascript tends to create less problems to maintain things over longer period of time
I'm not the guy you asked but I'm guessing he's referring to the "blessed way" of doing React, which seems to change every couple of years. Class components one year, pure components the next, functional components the next. A couple of years after that you're mad if you use React without Redux, the next year you'd be crazy to do Redux. State management a year later should be done with hooks, as should everything else. So what's going to be the next piece of guidance that will make our apps perfect?
From reading the RFC, I do feel like the choice for Vue.js was already made from the get-go. A few of the concerns laid out were brushed aside without much pondering (At least pondering within the thread, I don't know about the IRC channel)
Vue's deprecation process is still a big problem in my view. Migration from Vue 2 to 3 is a painful one, while React doesn't have this problem.
You can argue that component writing practices have changed over the past years in React, but the old ones all still work, while Vue 2 components just don't work in 3.
EvanYou's comments about a future "compatibility build" for 3 that works with 2 is honestly still a bit worrying. I'm glad it exists but it just so easily convinced them. Is there going to be a performance penalty? Will it all work out of the box?
> - Deciding on Vue 2 or Vue 3 including transition path
Am I the only one here who absolutely hates Vue 2? No TypeScript support and no type safety at all (neither for props, nor for events, nor for provide/inject); many identifiers and references are hard-coded strings, making it very hard to discover dependencies between different parts of the code; `this` gets implicitly populated with props, data, computed, methods all at the same time and in some order that still escapes me; refactoring support even in IntelliJ/WebStorm is full of bugs (hardly a surprise given the missing type safety); horrible documentation ("Here's an example" != documentation); no proper two-way binding (i.e. one that doesn't produce change detection cycles). I could go on and on and on…
That's the idea. Various tools and power-user features benefit from the things that modern JS frameworks give you. But the basic experience of reading articles should support the lowest-common denominator.
Most JS frameworks consider the SPA use-case to be the "happy path". There are a few outliers like the Stimulus family or Alpine (which I don't think existed at the time of the RFC) that expect to be sprinkled in to server-rendered HTML, but scaling these tools to full-blown apps may prove difficult.
I think Vue can operate in between these two use-cases better than some of the alternatives. Being able to compile templates at runtime is also a useful feature in a legacy environment, where you can't just transpile all the things ahead of time. You have to ship some extra code for this, but it's nothing compared to the cost of shipping (and running) all of Babel, which you'd need to compile JSX.
* ECMAScript has been evolving so quickly lately that it will probably supersede Vue in the near future anyway. The true "futureproof" choice is to continue evolving with the latest ECMAScript spec.
"htmx is small (~10k min.gz'd)"
Maybe I'm crazy, but that sounds huge based on the list of features in the docs. Would be interesting to see a breakdown of the features and how much of that size they take up.
Wish Vue would just adopt JSX. Any web framework that invents another templating language force users to learn a whole new thing with it's own gotchas. So much unnecessary mental overload.
Good luck getting any libraries working. Good luck using graphql. Good luck getting the tooling stable. Good luck getting a PR on the main code base done. Vue in production is a minefield of nightmares.
Rather have Facebook as a single point of failure than some random dude who has other things that consume his interest.
Are you trolling? I’ve used Vue in a couple of projects and honestly have no idea what you are talking about. Feel free to expand on your statements. Otherwise this message doesn’t fit in hn
The shift to Vue3 and a new paradigm (composition API) left the community in a state of confusion of where/how/when to migrate. The old paradigm is still supported but more like a legacy layer than the way to go. It reminds me of the python 2-3 schism.
I'm part of the community, several big production projects, several migrations from v2 to v3.
I was never confused.
The backward compatibility has a clean plan. For the bits that were complex changes, it was possible to do partial upgrades. From the beginning, the partial upgrade was in consideration. There was always early documentation, and you have access to v3 in alpha and beta all the time with complete documentation and complete guides. You also have standalone packages to start testing migrating bits of v3 to v2, like the composition API, class components, etc. It was one of the most seamless transitions I experience.
Reading through the RFC is really interesting. They specifically call out the dependency on Facebook as effectively being React's Single Point of Failure, citing their negative experiences with HHVM.
And for all of the love that people give React's big shifts (like hooks), the RFC specifically counts this against them, given that best practices have shifted so drastically in the last few years.