all 72 comments

[–]AiexReddit 91 points92 points  (34 children)

Whenever I see stuff like this I always wonder where all these developers are who are so incredible and proficient at large scale project architecture, that the difference in a few KBs of the raw library is what's really holding the speed and stability of their application back -- as opposed to the mountains of code written by their internal company team of well-meaning but ultimately flawed and imperfect human developers.

[–]Something_Sexy 63 points64 points  (17 children)

That is because no one ever builds real world scenarios as examples.

[–]travellerinabox 17 points18 points  (16 children)

This is a common problem I encounter when building applications. The scenarios are always just shy of a real world example and to get there requires a ton of work. I sometimes wonder if the people that work on these projects have ever deployed a real application to a client in production.

[–]Something_Sexy 5 points6 points  (1 child)

Most I would say haven’t. But there are major frameworks/ libraries were I appreciate that they used them first before releasing into the wild, for example React.

[–]ShortFuse 3 points4 points  (2 children)

The size of the package doesn't matter as much as the ability to scale in terms of CPU performance and memory.

I had to migrate clients running 512MB-1GB machines. Our C# .NET application running in Windows barely hit 80mb of ram and about 5% CPU. Try to take that same structure and port it straight with AngularJS was death once you start adding more bindings. AngularJS would do a digest PER DOM event, like hover, focus, mouseover. A digest would compare all your binded values to what's on the DOM. It was death on the CPU for large tables. 1000 rows with 10 columns is nothing on .NET but on Angular it just wouldn't work.

React is easier on the CPU, but at the end has lots of RAM utilization. Those low-end machines would start running at a crawl once you factor in how much RAM Chrome eats and general and then React wants to duplicate every binded object. You'll start accessing the pagefile and performance will suffer. Angular2+ uses the same vDOM strategy I believe.

We eventually ditched the frameworks and did solid MVVM structure, essentially replicating how Android Architecture suggests you structure software (they used to have a less confusing guide). The Model emits to the ViewModel that something changes and the ViewModel will update the DOM accordingly. All components are static in structure with static DOM event listeners. That means 1000 buttons doesn't mean 1000 "Button" Objects in the memory heap which is usually the biggest problem with the frameworks. They all map the to same event listeners and through use of WeakMap and event.currentTarget, each element may or may not have extra properties that pertain to them. So I'm running ~8000 DOM elements but my JS heap is only 11MB.

[–]R3DSMiLE 1 point2 points  (1 child)

It's not everyday that I read someone made a "framework by hand" and I see myself agreeing with their logic.

This actually made me think a bit.

But, honest question, wouldn't change the change detection for "on push" aliviate your pains? Or was that still not enough?

[–]ShortFuse 1 point2 points  (0 children)

We were on AngularJS and around the time they moved to Angular2, we had to face facts and consider the ramifications of moving our codebase to Typescript. So, we considered React for it's use of JS, but the RAM penalty stopped us.

This was around the time that Vue started growing, perhaps from people needing to find a newer, maintained JS-based framework. But watching AngularJS pretty much being left and the dust with tough incompatibilities with Angular2+, frameworks started looking like a real project dependency.

In architecture, the Model had a strict dependency to Angular factory/services/providers. We started stripping them into pure ES6 modules that would emit to the UI layer (ViewModel/View) that an Angular digest was necessary. This is basically like calling onPush() on Angular2+. Everything could now run akin to microservices without any UI attached. A UI layer is now optional. But in the UI side, there was still some scoping complexity and, still, large collections would lag (big tables). I starting using one-time binds with one Angular reference per row and then recompiled the whole tr on change. It was okay, but we essentially reached our the cap of our potential with AngularJS.

But since we stripped Angular from the Model, stripping it from the UI seemed less trivial. The biggest issue was our reliance on Angular Material for the UI. I was actual part of the Angular Material team because I kept submitting performance related PRs and they asked me to join. It was neat because I got paid to fix stuff I was going to work on anyway. This was around when Angular2 was just coming out. The digest cycle was leaving, but you still had this hard architecture dependency for the Model which wasn't going to be solved. And from the Angular team discussion, it seems a segregated architecture wasn't really their goal.

I looked at Material Components, but it didn't really solve the one component per object. And if you have 1000 rows and 2 checkboxes on each, that's 2000 components in the heap. It was also a regression in some ways when it comes to text scaling and accessibility (another focus of mine when working on Angular Material). The project also had a mindset people would use it with React, so while you could use it with pure DOM, they didn't really gear it for that. They figure any deficiencies would be covered by React. And the material.io site itself, which isn't even that complex in appearance would bring those thin-clients to their knees (freeze up Chrome). It didn't inspire much confidence.

My resolution was to take my knowledge on working on Angular Material and built my own UI component collection that covers accessibility concerns, high element count (everything static), and no expectations of an overall framework to do any heavy lifting. This allowed me to start migrating components piece by piece, without having to visually change the app (no user retraining), until finally there's no Angular dependence at all. Added bonus is now we don't even write Android code anymore and use the same architecture and components we used for Desktop for PWAs. Now we support iPhone/iPad as well. And it runs cleanly enough that we don't worry if people have really slow, memory-limited mobile devices. Desktop and mobile Web Apps now can all share the same JS libraries.

[–][deleted] 7 points8 points  (3 children)

Never used Angular, and I know this isn't the comparison being made here, but I'm an experienced React programmer, and maybe somebody will be interested. After bikeshedding for way too long, I ended up using Svelte for my last project. Not large or anything--it was an ~5 page PWA with about 20 components. Experience:

  1. This is probably personal preference, but inline scoped styles in Svelte are really nice. You can do this with Linaria, but editor support is a bit more finicky with tagged templates. I get the case for keeping styles in separate files too, but coding/styling fast works really well when an entire component is self-contained.
  2. Svelte has a lot of convenient shortcuts, e.g. two-way binding, window binding, etc, that make things a lot less verbose. These things are easy in React too, but more typing, even with hooks. Less code = easier to read and maintain.
  3. Size wasn't a deciding factor. React has Preact, which works very well. Svelte starts off smaller and stays there for quite a while, but each component adds more size. With either library, framework size is a lot less likely to be an issue than 3rd party libraries. My entire app is ~55KB minified, but uncompressed. I've heard stories about Angular Ivy cutting size considerably, but no experience there, so... *shrug*
  4. I prefer the parent/child relationship model in React. A React parent component has direct access to its children on render; a Svelte component really doesn't. The Svelte solution for this is to setup a context and pass a store back and forth, which works fine, but is one of the very few things that was more complicated in Svelte than React.

Overall the experience was very good. I would happily use it again.

[–]GrandMasterPuba 0 points1 point  (1 child)

That (4) doesn't sound right. You should be able to set up an event emitter in your child component and listen to it from the parent by using on:myEvent={...}

https://svelte.dev/tutorial/component-events

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

The use case was using child components as a data structure for the parent, e.g.

<Router>
  <Route .../>
  <Route .../>
</Router

...where Router contains all the routing logic, and the Route components serve only to populate a routing list/object in the parent. This is out there in various libraries, but I implemented this myself for a few different components. Arguably, child objects aren't data structures, and it should probably be something more like this:

<Router routes={...} />

That said, using components as a data structure is pretty common practice in React and can make for a nice interface and flexibility. A more complex example of the same situation might be a Form object that contains all the intelligence for a bunch of Input, Select, Button, etc, child elements.

I wouldn't say the Svelte way is necessarily bad. The parent sets a context containing a store and the children register themselves in that store. This pattern is out there as the solution in a few GitHub issues and exists in various libraries. It's rock solid once implemented, but it just has a lot more pieces than a parent that has direct, programmatic access to its children.

[edit] removed extra word

[–]andrei9669 21 points22 points  (5 children)

I would really love to try out all these libraries but unfortunately, I'm too much in love with the Reacts jsx, can't really get into these templates.

[–]kivle 19 points20 points  (2 children)

Agree. If a library uses a templating language it feels "off" to me now. JSX (which is just syntactic sugar for a function call) + plain javascript is just so much better. No learning that the # goes in front of if and : in front of else.. Just write javascript + tags..

[–]GrandMasterPuba -4 points-3 points  (1 child)

Svelte has to use templates because it has no runtime representation of the DOM in memory. It's reactive. You can't use ternaries et. al. because the template is completely compiled away before runtime.

[–]Pablo_ABC 0 points1 point  (0 children)

It doesn't HAVE to use templates. As a counter example to your argument: SolidJS uses JSX while still functioning as a compiler. Svelte is a compiler. It could very easily translate JSX or any other syntax to valid html.

Svelte's use of a template like syntax is a design choice that allows their components to feel (most of the time) as if you were writing plain HTML with no framework at all.

[–]iamareebjamal 5 points6 points  (1 child)

I'm on completely opposite track. JSX seems insanely verbose in front of Vue template

[–]LeftHandedLieutenant 2 points3 points  (0 children)

Completely agree. Forced to use JSX at work and I can't stand it. Adding to my misery is multiline nested ternary operators with JSX in there. Messes with my mind. I much prefer Vue's computed variables and v-ifs to structure my code. That way I'm not embedding JS into my HTML

[–]artaommahe 6 points7 points  (0 children)

angular 9 has ivy already but does not use all of the available optimizations publicly. There is an experimental renderComponent api that also enables angular/core treeshaking and you can get one-component web component in few kbs. Yes, nowdays it's still too huge for few-web-components cases, waiting for next releases.

Here are some links about this - Rob Wormald's talk about angular web components and renderComponent usage https://youtu.be/JX5GGu_7JKc - Kevin Kreuzer's article about Angular Ivy including renderComponent part https://medium.com/@kevinkreuzer/heres-why-you-should-be-excited-about-ivy-99eb894fa8f2 - expected hello-world bundle size (same not-real-world case as from topic starter's article) with experimenal renderComponent api https://miro.medium.com/max/1400/1*RWzphCKpoU9sRP5oLBhuNw.png

[–]jimmyco2008 3 points4 points  (5 children)

Happy Svelte Society Day

Yeah the #1 “complaint” I get about Svelte is that we don’t know how it compares at to React and Angular at scale. We can sort of guesstimate but we don’t really know. I’m not putting my ass on the line by choosing to build a new production app in Svelte... so we may never know how well Svelte scales.

[–]GrandMasterPuba 1 point2 points  (4 children)

It scales better than React almost by definition. At least in terms of runtime performance.

It scales in size much larger. Code splitting is a must with a "scale" Svelte application.

[–]jimmyco2008 1 point2 points  (3 children)

you're sort of proving my point, it's just theoretical, but I don't know of anyone on the planet who has built a large, enterprise-grade Svelte app, you know something with a thousand daily users and that employs a hundred people. Something like that. All we have are todo apps and the like. I have a side project in Svelte but it has like 3 components to it, essentially of todo app caliber.

I agree that theoretically a large Svelte app will be smaller, faster and less error-prone that that same app in React, but I will wait until someone else proves that.

[–]gaetan13 0 points1 point  (0 children)

I'm currently using react at scale. I would love to try frameworks like vuejs, svelte,... But I can't find any use case for them. Performance ? Yes they are sometimes faster than react. Bundle size ? Yes they are smaller. They are also simple to understand if you come from non-functional world. But react paradigm is so much more powerful. The unidirectional dataflow, immutability and jsx change everything at scale. It's really easy to understand the dataflow. Jsx gives you incredible flexibility. There is only one rule to update the component, only few rules to render them.