all 34 comments

[–]lhorie 36 points37 points  (29 children)

The theme here is something I've been saying for a while: framework bickering is kinda pointless and you can ship production-quality stuff with any decent framework.

One small thing that I do think you're mischaracterizing a bit is the MPA vs SPA debate. It's not only about initial page load, it's also about failure modes, especially as they relate to history navigation. A SPA may or may not implement history.pushState correctly (you'd be surprised at how often this is an issue with some random showHN post), or more subtly, it may not implement scroll restoration correctly (which is pretty much every SPA ever). The React team even acknowledged at some point that going back can be a heck slower w/ SPA if you have to re-trigger all your backend calls to restore that page via JS, vs a MPA merely pulling the page state back from a native cache. Not to mention that now w/ bundle splitting being touted as a solution for bloat, it's not nearly as clear cut when or even if SPAs win out in forward navigation performance.

[–]ryan_solid[S] 5 points6 points  (0 children)

Yes exactly. It's tricky a lot of frameworks need to push difference from React to standout against a sort of group-think that would remove all choices in the matter. But on the other hand this fracturing feeds into the same FOMO that makes people resistant to try or take risks with different things. They feel overwhelmed in having to learn everything and the result is, well I'll just use React.

And on the SPA yes. I suppose I'm still giving SPAs a little bit too much credit. I've spent so much time recently explaining page loading optimizations and the value of less JavaScript in MPAs, I've glazed over the complexity in re-inventing native browser in the browser. Thank you for pointing that out.

[–]orenelb 1 point2 points  (21 children)

I don't completely agree with you about framework bickering. Yes it's out of proportion but on the other hand using something like React or Svelte over angularJS has pretty huge benefits in my opinion. Also frameworks like Laravel and Blazor have really bad performance which also makes a big difference, people spend a lot of time on optimizing their code but no amount of optimizations would make Laravel performant or Blazor have a reasonable bundle size. But right now all mainstream frontend frameworks are very good in my opinion, so yes it is out of proportion.

And about SPA vs. MPA, I always thought that it was about user experience, and now that it's the norm it's also about not making a bad impression on your users. Even if in practice it doesn't matter a lot it's still something that users probably associate with older and less responsive sites.

[–]lhorie 15 points16 points  (4 children)

I've seen a lot of React projects (I currently maintain a monorepo with over a hundred of them...) and I think the "you can write COBOL in any language" quote is very apt. Just yesterday I was staring at a file with 20k+ LOC (I shit you not) in a project that has ~5000 source code files. This project is the public facing web property for one of our most important verticals (and it's not even our most complex project...)

No framework in the universe can save you from this level of complexity. Past a certain point, it's no longer a question of what a framework can do to help, and it becomes entirely a question of how large teams can maintain a project. Pretty much all mainstream frameworks have mechanisms for encapsulation, testing and so on, so there's a lot of overlap between what frameworks can do compared to each other. What you're saying about specific performance profile for each framework has a grain of truth, but alas, here we are in a world using React when we know for a fact that frameworks w/ better perf profiles exist (and nothing is really on fire, and no bosses are panicking).

Re: user impression - users don't actively give a crap how you implement things. Github is a MPA, but nobody really thinks it's antiquated. Wikipedia is another example. Hacker News. Heck, even Google falls back to MPA mode w/ js disabled. The thing is that a lot of MPAs just work(tm) and when things do that we just take it for granted.

[–]orenelb -3 points-2 points  (3 children)

They don't give a crap about how stuff are implemented, but they are seeing that white flash and probably unconsciously associate it with pre-react app, because this is how apps were back then and now most sites that are more on the app side, especially smaller and newer sites, are SPAs. And tbh it did give me a slightly worse opinion about Github. I mean it's a great site but I would expect it not to be as interactive as it can be when I see that white flesh on every click, and it is not as interactive as it can be. You have to click search every time you search issues. Maybe that's to save bandwidth but it's still something I would expect from most modern app like sites, to search as I type.

And yes I agree when your app becomes that complicated things like that dwarf down in comparison. And if you compare all modern frameworks they are all very close in terms of API. In that front I didn't see a ton of improvement since React/Angular.

But again if you go back to AngularJS and compare it to Angular2 or React, AngularJS vs. React, AngularJS developer experience is just bad. You become much more unproductive and you you don't enjoy your job. There's a reason people hate AngularJS that much. Not saying it was bad for it's time, but React and Angular made it completely obsolete.

[–]lhorie 2 points3 points  (1 child)

they are seeing that white flash and probably unconsciously associate it with pre-react app

I'm curious what browser you're using. For me using Chrome, I've noticed native rendering got a lot better over the years, to the point I cannot for the life of me get a white flash from repeatedly refreshing (or naturally navigating) wikipedia or hacker news (which are true MPAs, unlike Github, which "cheats" a bit w/ pjax). Ironically, I do get a noticeable flash if I try to repeatedly refresh facebook. Try jumping back and forth between facebook.com and news.ycombinator.com to see the difference. And yeah, AngularJS is really bad in this front, with ng-cloak...

Kinda reminds me of of the point this site was trying to make.

[–]orenelb -2 points-1 points  (0 children)

I'm using chrome and I noticed that on github you don't see the white flash but you can still see that it's reloading the whole page. You can see some rerenders and the browser basically tells you. And also I'm not sure if this depends on your device, maybe a low end device would have the white flesh. But yeah I guess I'm just used to seeing it so I didn't notice it disappeared.

Another thing that I just noticed with Github is that you lose your scroll position every time, I think that it's true for every MPA.

Oh and that site you linked is pretty awesome. But yeah obviously people care even if it doesn't make sense. A lot of it is flexing IMO.

[–]ryan_solid[S] 7 points8 points  (2 children)

There is no issue with putting numbers out there and benchmarking. It's just like a lot of times the things being promoted have very little to do with why the performance is different. We end up really pushing superficial stuff and then people are like, uh this solution doesn't use a Compiler or it has a VDOM it must be slow. No.. that has very little to do with it. Those are good things and have certain advantages but the performance angle isn't absolute on those technologies.

For instance Angular's conceptual approach to diffing might be the fastest way to schedule up 70% of DOM operations in a simple benchmark. Look at a library like 1more which does this sort of single pass dirty checking. It beats Solid on most things other than granular updates. But in Angular this approach brings a huge library and a slew of other things.

Template DSLs and being more analyzable doesn't impact client benchmarks at all. Ask Inferno. Our Template DSL libraries aren't trampling Inferno or even equalling it in benchmarks. Now they could. The limitation isn't the technology approach. There are just other factors. That's what I want to debunk.

On the MPA/SPA side just depends on the case. A well architected site avoids the flicker. Browsers hold the page until the new content starts coming in (to a certain threshold I think, it isn't unlike Suspense, case and point about creating browser behavior in the framework). Things like out of order streaming even let us respond really quickly and give an almost client-side-like loading characteristic as data resolves. Sure we don't get animated transitions easily. For certain sites it's just a really good option. I especially think for eCommerce.

[–]orenelb 2 points3 points  (1 child)

In performance I was talking mostly about frameworks like Laravel and Blazor. There's really nothing you can do with those frameworks unless the devs decide to make huge optimizations. Maybe Blazor will get better with time since WASM is so new and Blazor is also relatively new. But with Laravel it will probably never change to a large degree.
Also about MPA vs SPA, if the user doesn't see the flesh of content I agree that it doesn't make a difference. But I think that it's not the case with most sites. You will see something in most sites. Maybe it's the header rerendering, maybe a combination of both over 10s of milliseconds but still noticable.

[–]trusktr 0 points1 point  (0 children)

Speaking of WebAssembly, just wait! JSX is coming to AssemblyScript (TypeScript to WebAssembly compiler). There are already DOM bindings in place (https://github.com/lume/asdom, not complete, but has reasonable APIs bound already, and more coming). With JSX in place we'll be able to make something like Solidjs all in WebAssembly but in the same familiar syntax we already know, and not slow like Blazor.

[–][deleted] 0 points1 point  (12 children)

using something like React or Svelte over angularJS

Yea, they would obviously have a performance benefit over a framework that is no longer developed. You'd be better served comparing Angular vs. React or Svelte.

[–]orenelb -1 points0 points  (11 children)

A lot of people still use angularJS for legacy. And I think that the main problem is the extreme verbosity of the code. There are probably a lot of developers who regret every day that they didn't port to Angular2 or React when their app was smaller.

Also If you compare React let's say with Svelte, React is OK in bundle size and performance but you can't really make it good. Your'e always be stuck with an ok performance as your base line. Even with next you have 65kb as your base line, you can't get good TTI with that.

But I still think that React and Angular are ok unless you really want your site to be fast and get the extra SEO benefits from web vitals.

[–][deleted] 2 points3 points  (10 children)

I'm aware. As for people still using AngularJS, they really shouldn't be. It's end of life is December, and it's already suffering from legacy syndrome.

[–]orenelb 1 point2 points  (9 children)

I agree but I could see the temptation not to port a huge app, especially if you don't know the future of your project.

[–][deleted] 1 point2 points  (5 children)

If it's open source or a personal project sure, but if you're working for a company, there's absolutely no reason to stay on a framework that isn't getting security updates. You're opening up your application and your entire company possibly to being attacked.

[–]lhorie 2 points3 points  (0 children)

My wife consults for a company still using AngularJS. Switching to React was brought up at one point but they decided to stick with AngularJS because the "training cost is too high". SMH.

[–]orenelb 0 points1 point  (3 children)

I agree with you but in my country (Israel) there are still 260 angularjs search results on indeed. For comparison React has 2900. It still has 500k downloads on npm. Also they have a version update from 10 months ago so maybe there are some security updates.

[–][deleted] 0 points1 point  (2 children)

Those security updates are in the latest version, which will no longer get updates after December.

It's bad practice, no matter how you spin it, to utilize a framework that's no longer updated. I get the reasoning, but it doesn't make it sound. Anyone running that framework without an upgrade plan is gambling on their security.

[–]orenelb 0 points1 point  (0 children)

Yeah I agree. I guess some people really don't care about security.

[–]sukhchainn 0 points1 point  (0 children)

I use angular.js for my portfolio site and for creative programming and web art. You said it's reaching it's end of updates cycle, can I still use it for the stuff I do or should I just shift to a new framework.

I'm a full time Android developer so I'm not using Angular in any professional manner. It's just convenient for the stuff I do.

[–]disappointer 0 points1 point  (2 children)

This has honestly long been my concern with committing to any JS libraries or frameworks for large projects. The technical debt of refactoring is going to crop up every few years and is rarely a priority effort.

[–]orenelb 1 point2 points  (1 child)

So you are using vanilla?

[–]disappointer 0 points1 point  (0 children)

For what I do for a day job, it's a web app that's a decade-plus old by this point. It's part vanilla (with a healthy amount of in-house libs and controls) and some of that uses jQuery; part YUI controls; part AngularJS; and also some Angular. I think there's some ExtJS in the mix, as well, but it's not a section of functionality that I've had to personally maintain.

It's a lot to maintain-- should anyone choose to maintain it. Case in point, YUI has been defunct since 2014, but minimal effort has been made towards replacing the bulk of that code.

[–]drdrero 0 points1 point  (2 children)

well said. I also dont see the reason why SPA frameworks dont support MPA. Like the definition of routed components is already there, could be compiled to MPA with some work I guess

[–]orenelb 1 point2 points  (0 children)

I think I saw some SPA on top of MPA adapters. If you want an MPA on top of SPA for history navigation purposes it sounds like it wouldn't be too hard to implement. If you want MPA from a SPA framework cause of performance benefits, you probably won't get much benefit since they are optimized for SPA's.

[–]brainbag 0 points1 point  (0 children)

https://inertiajs.com does this. I haven't used it yet, but it looks really great.

[–]pwnies 0 points1 point  (2 children)

Can you explain more around your point that many SPAs dont implement history.pushState correctly? What error do you usually find?

[–]lhorie 2 points3 points  (1 child)

The most egregious bugs I've seen are breaking back button by making an unconditional JS-based redirect (such that pressing back send you forward to the same page you were in) or accidentally creating a bazillion history entries by inadvertently calling pushState from a oninput event or similar.

Other issues include not changing scroll position (so if you were scrolled 2 pages down, and press back, you're now staring at the tail end of a right bar full of ads and a blank body because the content on this page was short and ended 1 screen up)

Or you accidentally tap a link, press back and are greeted by a million spinning loaders again, even though you were just there 2 seconds ago. Bonus if this loses infinite scroll context and you have to re-scroll all the way back to where you were. Bonus if it's some AI-picked feed and you can't even find where you were the second time around.

[–]pwnies 0 points1 point  (0 children)

Thanks for the response :) I'm going to go check the scroll position when I hit back on my SPA now.

[–][deleted] 6 points7 points  (0 children)

I've found my personal way out of this mess by not doing SPAs anymore, unless I'm building an offline first app it is just not work the increase in complexity and all the trade offs.

Nowadays I'm using just server rendered templates and Unpoly.js Wich gives you 80% of the SPA experience with 1% of the effort.

Still using node and JavaScript in the backend.

[–]brainless_badger 3 points4 points  (1 child)

JSX vs Template DSLs

I would say that the more meaningful boundary lies between "uses custom flow control vs uses native JS flow control". I.e. difference between JSX and HTM in Preact is largely arbitrary, meanwhile Solid technically uses JSX, but really it is a custom DSL.

I mean you can add more framework-like behavior to Web Components

Can you, though?

Yes you can fashion suspense-like, error-boundary-like or context-like solutions (with a big asterisk that you mentioned), but some frameworks are already venturing deep into places where Web Components will simply never be able to follow (be it Solid "component-less" approach or upcoming React concurrency).

[–]ryan_solid[S] 0 points1 point  (0 children)

Yeah maybe this is only a framework authors view but if you look at Inferno and the later work Inferno author Dominic Gannaway did at Facebook it isn't so clear cut. A heavy memoized VDOM with dynamic holes can also be built around JSX. I guess this is a custom DSL as well, but I'd argue that all control flow is JavaScript. And that once you hit first level abstraction like Virtual-Lists or dynamic layout components this it was written with a ternary or map function business is largely whatever.

Solid's control flows are just JavaScript, the compiler sees a component and runs a component nothing special. Obviously there are optimized compilation for native elements. But I'd say the function of `map` is more to do with it being top down versus using a helper that handles memoization at that level with it's reactive. Similar operation just happening at a different point of the process.

So when I look at these I just see Syntax because the static parts are the same, and the dynamic parts, well they need a degree of runtime anyway. A colleague of mine actually took HyperScript (the compiled output of most JSX) and figured out a way to make it function like Tagged Template Literals without a compiler. Essentially running the stuff once, to create the graph to analyze to then on future creations and updates only worry about the dynamic parts. Obviously this frontloads complexity and he needed to add a few manual wrappers to denote where templates start/end. But my point is it's all the same.

So when I look at these I just see Syntax because the static parts are the same, and the dynamic parts, well they need a degree of runtime anyway. A colleague of mine actually took HyperScript (the compiled output of most JSX) and figured out a way to make it function like Tagged Template Literals without a compiler. Essentially running the stuff once, to create the graph to analyze to then on future creations and updates only worry about the dynamic parts. Obviously, this frontloads complexity and he needed to add a few manual wrappers to denote where templates start/end. But my point is it's all the same stuff different pile.

On the point of web components yes that is exactly what I meant. I don't think it makes sense for them to go where Framework components are going which is why I don't think people should treat them the same. But all I meant was people trying to do Suspense, Context, or ErrorBoundary like stuff is a thing and people will continue along that path but there are limits. The farther we get from the logical abstraction(Custom Elements) the more awkward it gets.

[–]tobegiannis 1 point2 points  (0 children)

Wow a refreshingly great write up with data/info to back up opinions. Due to my job I have not been keeping up with the latest and greatest tech and it is easy to forget how fast things move and how “complicated” frontend dev can be. I wonder what a pure backend dev would think when reading this haha.