Readit News logoReadit News
kilburn · 6 years ago
Most people here are criticizing the author for doing some dumb things. I concur, but still think they have a good point.

First, keep in mind that the author's use case is a content-heavy app with sprinkles of interactivity. This is very important because it sets the "webpage speed" goalpost to a concrete place: they want good lighthouse/first load times and good SEO.

I've fallen into the same pit before. I've used Create React App with a custom server-renderer, Gatsby and Next in different projects. None of the solutions is truly satisfactory for the author's use case for a single very strong reason: React's hydration process is both blocking and slow. I hope that sooner rather than later React is able to offer a good solution for incremental hydration, but it seems quite far for now.

Once you realize this, the only way to keep using React is to step out of the mainstream and play with multiple render roots, parts of the page that never get hydrated and so on. It is possible to do things here, but it is definitely a rocky path.

Of course, there are many wrong things the author explains that you can avoid, but I'll throw a bone to them here too. Most "wrong things to do" they explain are both wrong and understandable. And they openly accept it.

For instnace, one wrong thing to do that I've had to fight against a lot is JS-based device-specific rendering. It is so much easier to implement a "mobile ? <MobileScreen /> : <DesktopScreen />" than to make a single screen that adapts properly using CSS that it's not even funny. Unfortunately, it also breaks SSR, leads to janky page-loads and poor performance.

I fully agree that as of today and for content-heavy sites React pushes you towards a pit of despair instead of a pit of success. You can make it work, but ... is it worth it?

aphextron · 6 years ago
It's just apples and oranges. Web pages should never even consider using React. Maybe a bit of vanilla JS/jQuery here and there for whatever interactivity you need, and then server side rendering for the content. Building web applications on the other hand, has been revolutionized by the use of React. I would never seriously consider any other UI rendering library right now because of the sheer volume of support and active development around it and its' ecosystem. And hand rolling vanilla JS in a large scale web application quickly becomes a maintainability nightmare. The alternative of doing things old school with server side templates is ok, but it massively slows down your iteration speed through reliance on tight coupling between backend and frontend.
tomc1985 · 6 years ago
> The alternative of doing things old school with server side templates is ok, but it massively slows down your iteration speed through reliance on tight coupling between backend and frontend.

Huh? Something like Rails lets you iterate on server-side stuff extremely quickly. There is a lot of functionality you can implement that doesn't need JS at all

gvjddbnvdrbv · 6 years ago
> The alternative of doing things old school with server side templates is ok, but it massively slows down your iteration speed through reliance on tight coupling between backend and frontend.

This depends on project size. If a single team is working fullstack then using server side templates gives seriously faster product development iteration. Once you get to more than 5-10 devs and you want separate frontend and backend teams then it slows down.

RandoHolmes · 6 years ago
This all indicates that browsers and html/css are bad tools for creating UI.

Long term I think we'll eventually see the ability to interact with the local system via the browser, and we'll start seeing more things like "QT for the web".

Because if we don't, at some point it's all going to just fall over.

bmarkovic · 6 years ago
It is also a frustrating experience to endure reloads on every click if what the user is using feels like a web application and you're essentially placing that burden of reducing the interaction roundtrip time on your infrastructure which gets expensive really really fast.

Most web-thingies are neither 100% plain websites nor 100% plain webapps, most are in the middle, some are heavily leaning on one side or the other.

bromuro · 6 years ago
You don’t need even build always a SPA with React. For interactive widgets, Resct works better to me than jQuery.

Deleted Comment

Shorel · 6 years ago
And who decides which is which? You?
kbenson · 6 years ago
I stop reading the webapp/react specific posts on HN for a year, and now there's such foreign terminology that I can't even understand the comments of one. Hydration? From context I assume it's something to do with rendering trees and the Dom, but really, I'm just grasping.

So out of hand. It feels like Javascript webdev is recursively devouring itself into a completely separate type of programming.

kilburn · 6 years ago
hydrate [1] is the API call by which you tell React to initialize itself against a pre-rerendered DOM. In contrast, render [2] is the call by which you tell react to generate the DOM nodes itself.

The idea is not that complicated:

1. You send the page's full HTML to the client. This is good for SEO and to quickly get the page to show. This HTML has been generated by running React on the server and capturing the output.

2. You send the React stuff (React itself, your pages components, extra libraries you are using, etc.)

3. You hydrate React's virtual dom using the already existing DOM (that the browser has created in step 1). This essentially amounts to telling react to attach the proper event handlers to the DOM so it can continue working as if that DOM was created by React itself.

[1] https://reactjs.org/docs/react-dom.html#hydrate

[2] https://reactjs.org/docs/react-dom.html#render

pqb · 6 years ago
"Hydration" is a term often used on the backend too. I believe I have noticed it for the first time in Doctrine documentation, Object Relational Mapper (ORM), which is similar to Hibernate in Java - it was about transforming data retrieved from SQL database (memory) into usable PHP structure (object) [0]. In my opinion, this term has been perfectly described on the StackOverflow [1].

[0]: https://www.doctrine-project.org/projects/doctrine-phpcr-odm...

[1]: https://stackoverflow.com/a/6991192

beaker52 · 6 years ago
Wow, hello quantumly-entangled developer twin. All this Gatsby, Next, React hydration, multiple roots stuff is what I'm traversing at the moment. Even down to the `<MobileScreen /><DesktopScreen />` example. I'm having discussions about these things almost every day. And then to finish it off, you mention the pit of success which has been a key focus of my recent attention too. I could imagine myself writing this exact post, even down to the word 'janky'. I had to check to see if you were a colleague of mine, but I doubt you are.

Since we're tackling similar problems, do get in touch with me if you want someone to share ideas with in future.

crooked-v · 6 years ago
When it comes to the mobile-desktop thing, check out Rebass, which uses actual generated CSS under the hood so it's properly performant (especially if you handle it right by precompiling all the static CSS at build time with babel-plugin-emotion), but lets you write media query-dependent attributes directly with your component use. For an example: https://rebassjs.org/box and resize the page back and forth
cityzen · 6 years ago
Kind of off topic but when the word "hydration" become a technology term? I see it all over and it's never really made sense to me. The definition is specific to fluid:

1 : to cause to take up or combine with water or the elements of water 2 : to supply with ample fluid or moisture

Maybe I'm old school but the word "populate" makes a lot more sense than hydrate when talking about data.

RandoHolmes · 6 years ago
think powdered milk. You hydrate it by adding water.

Same idea, only for objects. You hydrate them by adding data.

The term has been used for probably 20+ years.

nprateem · 6 years ago
Over 10 years ago with various ORMs.
city41 · 6 years ago
React supporting selective hydration would potentially be a total game changer.

I have recently started using gatsby-plugin-no-javascript. It's a very crude version by removing hydration at the page level. It works pretty well for me because my site is a ton of static pages and then one very interactive app page. I get to build it all in React, get a great developer experience, and then all those static pages are like 20k total (css, images, html, everything) and load in the browser instantaneously.

If we could get this ability, but be able to apply it at a finer granularity than pages, we could probably do some really great things.

shepmaster · 6 years ago
> gatsby-plugin-no-javascript

Thank you for mentioning this! I’ve been on a passive search for exactly this: the ability to use React and generate a completely static site without even the possibility of JS at runtime.

bmarkovic · 6 years ago
I've only used Vue SSR / Nuxt this way, so there might be a fundamental difference in the implementation, but hydration process in it isn't blocking, and whether or not it's slow greatly depends on how heavy your webapp is.

The page that he browser is hit with has ALL the content pre-rendered (sans CSS) in that first HTTP HTML response, and it behaves like a classical webpage henceforth until the moment that the interactivity bits are being hydrated which is deferred.

I concur that it's still a bad idea to use SSR SPAs for use-cases where a non-dynamic HTML page would work decently well, and there are ways to pack some of these frameworks (Vue in particular) so that it's a JS dependency of an otherwise functional webste (i.e. progressive degradation) for a lot of the in-between use-cases, but when what you're building is heavily leaning towards being essentially a web application (say, an e-commerce site, webmail client etc) then SSR is certainly the most viable option for a decent user experience that isn't full reloads on every click, but also doesn't take ages to become interactive.

kilburn · 6 years ago
> The page that he browser is hit with has ALL the content pre-rendered (sans CSS) in that first HTTP HTML response, and it behaves like a classical webpage henceforth until the moment that the interactivity bits are being hydrated which is deferred.

That is what Gatsby / Next.js do too. The issue is that deferring the hydration doesn't mean it is neither non-blocking nor quick. Once hydration is triggered, the browser gets blocked until it finishes. Of course, the speed of the process depends on the site and how much content it has. If you are building an e-commerce site, this will tend to be on the side of heavy (just the full menu structure, footers and such will be quite a lot already).

> but also doesn't take ages to become interactive.

The issue is that a regular old website can be interactive almost immediately. If you have a hydration process interactivity is inevitably delayed for any part that does require javascript to function... and also for the parts that don't, because the browser main thread is blocked for a while doing the hydration and won't respond to your inputs until it has finished.

If you don't believe me, open an incognito chrome window without any active extension, go to nuxt's own documentation site [1], run a lighthouse performance evaluation with the default settings (mobile/simulated) and see what scores you get.

In my laptop it is a 33 overall for performance, with 4.1s FCP, 9.2s TTI, 6.1s LCP and a total blocking time of 2.41s.

You can also test from https://web.dev/measure/, where I'm seeing a 57 overall (much better, but not good) with 3.5s FCP, 7.8s TTI, 4.9s LCP and a total blocking time of 500ms.

That is, the creators of this software have built a documentation site (i.e.: mostly text, very little interactivity) that doesn't get good performance scores. This, along with blogs, is the best use-case I can think of for the technology. And it doesn't perform good (according to Google's-defined objective metrics, not mine!).

[1] https://nuxtjs.org/guides/get-started/installation

aabhay · 6 years ago
Vue’s hydration is much better, partially because the templating system allows more of the pages to be rendered. I’ve had react apps that had various convoluted systems that ended up rendering as basically blank pages before hydration due to dynamic state based on cookies, etc.
davidwparker · 6 years ago
If you're truly having issues with CSS and rendering different sizes, I'd recommend taking the time to really learn CSS inside and out. I find it incredibly simple nowadays to do both Mobile/Desktop (+Tablet) with CSS and media queries. I may have agreed with you in the past, but not so much anymore.
kilburn · 6 years ago
There are still some things that are impossible to achieve with CSS alone, even if you have the luxury of only needing to work with evergreen browsers (remember we are speaking of content-heavy sites here, which are the most prone to still have to support older browsers).

Example: I have a stack of boxes of varying heights. On mobile they are fine as is (one below the other). On tablet I want them in two columns but displayed in column order without gaps. On desktops I want three columns. This is dynamic data, so the number of items and their heights will vary, but my CMS allows the user to mark at which box(es) new columns should start:

  mobile  tablet  desktop
  a       a  c'   a  b* d*
  b*      b  d       c
  c'
  d*
' indicates this element starts a new column for tablets (two-column layout)

* indicates the element starts a new column for desktops (three-column layout)

Can you achieve this with HTML/CSS alone? How?

- CSS columns won't work because Safari doesn't support break-brefore in a columns context.

- Flexbox won't work because you don't have a defined height for the container (so you can't use flex-direction: column + flex-wrap).

- CSS grid won't work because you'll get a grid (i.e.: gaps between elements when the boxes have varying heights).

- Ye-olde-floats won't work because you'll get weird gaps too when the sizes change.

- You cannot wrap the elements in column-divs because you can't do it for both tablet and desktop simultaneously.

Also, you need to be very confident in all of the above to know that is is not possible, instead of getting sucked into trying, getting to an "almost there" point and then realizing it doesn't work under X condition.

In contrast, with React you can just generate 1/2/3 wrapper divs depending on whether the current width is mobile/tablet/desktop and call it a day. It takes you all of 5 minutes to do so and the margin for surprises is 0.

Edit: reworded why flex won't work to address nawgz's comment.

recursivedoubts · 6 years ago
The initial motivation for intercooler.js (which the author forked) was performance. I was working on a large bulk table update and building the table dynamically in javascript. The performance was terrible (this was back in 2012, no idea what it would be like today).

I realized that I could just deliver and slam HTML into the DOM and that the browser engine, written in C, was very fast at rendering it.

That turned into a pretty big javascript function, which then turned into intercooler, which then turned into htmx:

https://htmx.org

chias · 6 years ago
This is everything I never knew I needed.

At a glance through the docs, I'm pretty sure I can replace about 30% of my website's javascript codebase with this. Not to mention that having to actually write the javascript to "spruce" up a form will often lead me to be lazy and just have people deal with an un-spruced-up form.

I'm itching to get off work and try it out for real :) Thank you for all the work you did on this.

nightski · 6 years ago
I could definitely see something like intercooler boosting productivity. My only concern (possibly unfounded) is that you end up designing all of your server side endpoints specifically in an intercooler fashion. All of your endpoints must now return an html snippet, which is specific to the design of the page. So you have a lot of page specific endpoints. This is in contrast to a REST api where the api can be designed largely independently of any one use case.

If you ever need to switch away from intercooler you are going to have a large undertaking not just on the front end, but now on the back end as well.

But I might be missing something.

mattmanser · 6 years ago
If you don't need a rest API, all it does is make everything far more complicated, i.e. every page now has two end-points, one for the html, one for the data.

It's trivial in most web frameworks to have an endpoint respond in two ways, one with all the html including head, menus, footers, etc. if you hit it with a GET, the other just the snippet if you hit it with an Ajax request.

A REST API is basically a massive over-complication unless you actually need it for a good reason, say you're running both a web app and a mobile app from it.

I've used this technique occasionally for over a decade and personally have always found this server-side approach very simple compared to juggling REST APIs with client-side rendering when a client or an existing code base demanded it.

I've also always found the defence 'you might need to switch' to be a flimsy one. Usually when you do need to switch, everything is so different even your 'future-proof' API design needs a massive overhaul too because you made assumptions you didn't even realize you were making.

Think of all those SOAP or XML APIs that were future proof...

recursivedoubts · 6 years ago
Yeah, I would recommend adopting htmx (or intercooler) incrementally, where it adds the most value. And when it doesn't "feel right" for a particular use case, don't use it there. This minimizes your commitment to the approach and lets you use the right tool for whatever UX job you have at hand.

EDIT: I should have read your comment more closely. With respect to two end points, one html and one JSON: I view the JSON and HTML end points as separate problems that both benefit from not being conflated with one another.

Your HTML end points are tuned to the particular use cases for your UX (e.g. active search) with the caching and tuning required for your specific needs.

The JSON end points need to be general and support unknown 3rd party client needs, and thus require more expressivity (e.g. GraphQL) at the cost of not being tuned for particular use cases.

I tried to get this idea across in this older blog post:

http://intercoolerjs.org/2016/01/18/rescuing-rest.html

flukus · 6 years ago
> All of your endpoints must now return an html snippet, which is specific to the design of the page. So you have a lot of page specific endpoints.

This is ok, adding an endpoint to spit out html is super simple, it's just printf statements with angle brackets.

Beside that I find endpoints need to be somewhat coupled to the UI anyway, otherwise the endpoint needs to be a superset of all possible data and all the complications that come with that.

edoceo · 6 years ago
When you migrate away from intercooler the new front-end is loading some data-api and some html-blocks from the old way. Move them out in increments.

Intercooler is great for some cases and can make a good transition step moving from all server-side v1 to a fully responsive/dynamic v3

JeremyNT · 6 years ago
I love seeing more work in this space! This sounds similar to the approach Basecamp has taken, with tools like stimulus.js (combined with with Rails UJS and Turbolinks). You can make a really responsive page with normal server-side HTML templates that "sprinkle" in the ajax functionality.

Tools like this feel very familiar to those of us who got started before the rise of the modern JS framework. It's kind of fun to see articles like the OP's pop up where people are rediscovering these techniques.

recursivedoubts · 6 years ago
Yep.

The problem is that HTML was never completed as a hypertext, they just kinda stopped at anchor tags and forms.

There isn't a good reason that only anchors and forms should be able to specify HTTP requests. There isn't a good reason that only clicks or form submits should be able to trigger HTTP requests. There isn't a good reason that only POST and GET should be readily available (and POST only for forms.) And there isn't a good reason you should have to replace the whole page on every HTTP request, rather than a component within it.

htmx is an attempt to complete HTML as a hypertext.

romaniv · 6 years ago
http://quickenloans.github.io/Behaviors.js/

Once I got past certain mental blocks, it became fairly obvious that you can structure all your GUI scripts to be configured and to interact with one another via DOM.

The next insight was to use CSS selectors for targeting.

Then using consistent name prefixes and separating behaviors into self-contained libraries.

The stuff above was proof-of-concept. The possibilities behind this approach are mostly unexplored.

corytheboyd · 6 years ago
I love seeing people invest time in this area, kudos. One thing that’s a bit hard for me to justify though are the examples like “click to edit”. There is a very noticeable delay as you wait for the network request with the edit document, whereas you typically won’t see that with client-side view logic. Is this just not a problem that htmx is trying to solve?
recursivedoubts · 6 years ago
That response will be as fast as your server is, which is typically fast.

I stuck a 300ms delay in the mock server to make it seem a little less instant:

view-source:https://htmx.org/js/demo.js

I didn't want people to think I was misleading them about what was going on. I would typically expect a simple edit form to return in sub 50ms.

bharani_m · 6 years ago
This is really interesting. Thanks for all the effort you've put into this project.

I had one quick question - how easy/difficult would it be to integrate another JS library with intercooler or htmlx. For example, let's say a table is fetched dynamically via htmlx, how would we go about integrating a library that does client-side table sorting/filtering?

recursivedoubts · 6 years ago
It's not perfect, but not awful either. Basically you have to catch the content and initialize it with the library using a hook:

htmx.onLoad(function(content){myJSLib.init(content)})

Blackthorn · 6 years ago
Wow, that's awesome! Would have definitely made some stuff I've done a lot easier.
vijaybritto · 6 years ago
Is it possible to make components like Dropdown with autocomplete in this? Should we be making use of Extensions for that?
recursivedoubts · 6 years ago
It isn't really component focused, but there are patterns like active search:

https://htmx.org/examples/active-search/

Htmx can be used to implement reactive components, however. Ben Croker created the Sprig component framework based on it for Craft CMS, for example:

https://putyourlightson.com/plugins/sprig

revscat · 6 years ago
This is amazing.
tom_walters · 6 years ago
This is the typical "we didn't spend any time thinking about our architecture therefore we're going to blame our framework" article.

React is a great choice for certain use-cases, but when low-quality developers are allowed to pick it up and apply it to everything you end up in a mess. The same thing happens with literally any tool.

If you want speedy initial interaction times and manageable codebases, (and requirement X) use the right tools for the job, and instil better, thoughtful, development culture.

Udik · 6 years ago
In general, these posts sound a bit like this: I tried jQuery, and after a while it all became a mess; took up a Backbone project, and was good for a while, but eventually it became too complex; then I worked on Angular and that seemed a big improvement, but then... and finally with React my architectures are clean.

While the reality is more like this: I had 6 months of programming experience and used jQuery and made a disaster; with 1.5 years of experience I used Backbone and I fared better; with 3 years of experience I tried Angular and I was able to build a decent size application but ultimately shot myself in the foot; and now that I have 6 years of experience my software quality has improved a lot, it must be react!

tom_walters · 6 years ago
Pretty much. It's similar to discovering the power of salt and pepper in cooking. When you first use it everything tastes better. But the next step is not to increase the amounts you use in every dish, it's to explore the much wider world of cooking with herbs/spices/etc.

If your mindset is persistently "this framework/tool will solve all our problems" you're always going to have a bad time. Understanding the pros/cons of each element is essential to becoming a good developer.

mgkimsal · 6 years ago
I would change it a bit and suggest that after angular, they did react, and after 18 months of that it was too convoluted, but 'hooks' solved everything, and then 12-18 months after that, things are just way too complex, and they're now investigating svelte or something else.

I rarely see any decent architecture survive growth and real world use beyond a couple years. It's usually either 1) "no one could possibly have foreseen this new use case/requirement" (from less experienced folks) or 2) "YAGNI!" when trying to build in some abstraction levels to handle use cases you know will happen down the road.

dangoor · 6 years ago
I disagree with the reality you present. There are a lot of people, myself included, with a considerable amount of experience who found that maintaining jQuery/Backbone code to be complex and error-prone and React presented a solution to this problem with a programming model that looks more like an immediate mode GUI (even though it ultimately paints to a retained mode DOM).

I don't think it's worthwhile to minimize the actual, useful impact React has had for web apps.

christkv · 6 years ago
React has been god sent for us as we slowly modernise an application that is a mess of server rendered html and hacked together frontend code.

Slowly we are rewriting individual pieces as embedded React components (no SPA here) and moving to a proper API layer that the components talk to. The separation of concern has made it a loot easier to increase code coverage and ensure a controlled rollout of new features.

We also just bit the bullet and paid for syncfusion to use on our frontend to avoid reinventing the wheel for a lot of the functionality we need.

mixedCase · 6 years ago
> The separation of concern has made it a loot easier to increase code coverage and ensure a controlled rollout of new features.

This can be achieved (and more easily) by separating your templating from your business logic at the package level. If you know what you're doing you can keep things separate and your import graph non-cyclical, if you don't know what you're doing you're going to recreate the mess in your components and API anyway.

Source: Tired of seeing this happen again and again and again and again. And fixing it.

_fat_santa · 6 years ago
Honest question. As someone whose only worked with open source tech in React such as Bootstrap, Semantic UI, Material UI, etc, what is the advantage of a paid UI framework like this?

Maybe stability? Besides Semantic UI I found that other frameworks are nowhere near as mature. I guess if you're a big company its a small price to pay but it also seems like you're paying a grand + per month for something with tons of free alternatives.

toddmatthews · 6 years ago
godsend
untog · 6 years ago
IMO it’s unfair to blame “low quality developers”. The industry has coalesced around React as the one stop answer to everything. Coding boot camps focus on it to the detriment of broader web technologies. It’s worth calling out when it actually fit a use case.

Dead Comment

capableweb · 6 years ago
> we’ve discovered that React also leads to some questionable practices. Like hovers in JS (rather than in CSS), drop-down menus in JS, not rendering hidden (under a hover) text (Google won’t be happy), weird complex logic (since it’s possible!), etc.

This is some strange reasoning that I have yet to seen myself. If you can do the hovers states/drop down menus in CSS, why not do them in CSS, even if you're using React? Seems to be blaming something on a library that the library has no care about in the first place (which to be frank, seems relatively common in web dev circles).

> In the worst case, we would serve you 2.5MB of minified (non-gzipped) JS

And holy guacamoly, how do you end up with this?! Seems that something was surely wrong in the compilation options, forgetting to mangle names or something, missing dead-tree elimination maybe?

Etheryte · 6 years ago
Talking of bundle sizes, this isn't inherent to the React point being made here but it's arguably too easy to blow up what you're serving. A common example I like to reference is Moment[1] — unpacked size is 4MB, most of which is different locales. If you _don't_ want to bundle all of those with your project, you have to do extra work, instead of making locales opt-in. Perhaps slightly less used, but a more prominent example, a widely-used table component Ag-grid[2] is 25MB before being packed down. Instead of being served as a modular set of components, it's mostly a big blob with minimal separation of concerns.

The takeaway here is twofold: we need better tooling as well as better practices for how to use those tools. It's both an educational problem as well as a toolset issue. It is possible to build lean and fast pages, but it's currently considerably harder than building gargantuan monsters. I don't see the web bloat problem going away until the dynamic here is flipped — it should be easy to ship small bundles even with minimal experience.

[1] https://www.npmjs.com/package/moment

[2] https://www.npmjs.com/package/ag-grid-community

andrewingram · 6 years ago
At my last job I always tried to be quite strict about adding additional dependencies, if something was over 10kb it had to be very strongly justified.

Our designers wanted to add some SVG animations, they started off with Lottie (https://bundlephobia.com/result?p=lottie-web@5.7.2) because they could export directly from After Effects, but I said no chance because of its file size. Briefly considered Greensock (https://bundlephobia.com/result?p=gsap@3.5.0), but it was also too big for the kind of animations we were looking it.

I'll need to double check what we ended up with, but it didn't have any library code, so each animation was just a self-contained bundle of SVG and CSS animation code, and fairly small.

Edit: I asked around and SVGator (https://www.svgator.com/) is what we ended up using.

avasthe · 6 years ago
Tangentially related; is there no lint option (similar to use strict) in JS yet to ensure no methods / functions are dynamically called and thus allow effective dead code elimination?
hombre_fatal · 6 years ago
That first quote (using JS when CSS would be faster and simpler) does remind me of being a beginner and always arriving at jQuery's animate() for all my needs.

That said, animation is hard, and React doesn't insulate you from that, so it takes some thought. In fact, being a layer of abstraction, it requires even more understanding of animation. Fading a component in is easy with regular CSS transitions. But fading a component out generically means that you have to keep the component mounted for the transition.

Perhaps anyone who has used react-bootstrap's Transition system (animate={true} on modals and tooltips) has run into those quirks where you start seeing a pattern of animate={false} fixing all sorts of random bugs.

With React, if you're grabby with 3rd-party libraries, you can end up with a russian doll of HoCs, each one from a different library, that are so generic that they kill performance and it's not even obvious why without being a profiler expert. Whereas without React, you wouldn't have found those solutions at all, so you roll your own cross-cutting solution.

That isn't necessarily a problem with React, but something that you have to resist with frameworks in general. It reminds me of Ruby on Rails, googling "rails avatars" and ending up with two libraries like carrierwave + "has_avatar" when you could have just built your own simple solution. It's a form of technical debt. After all, it's hard to justify the effort of deabstraction when you're assigned to 100 other issues.

Jestar342 · 6 years ago
RE: jQuery.animate() - that was around before CSS animations were. Animations were not in the CSS spec until v3 which only saw widespread support this side of 2010.

Before then you could only do animations with Javascript, and frankly jQuery's `animate()` was a god-send.

ricardobeat · 6 years ago
> Seems to be blaming something on a library that the library has no care about in the first place

Libraries and frameworks establish idioms, which encourage or discourage certain patterns. In my experience React / JSX definitely encourage complexity and abstraction by making display and logic so intertwined, especially with hooks.

> And holy guacamoly, how do you end up with this?

Libraries upon libraries, one tiny problem at a time. Unless you're in a very small team, or have very strict policies for adding new dependencies and vetting their impact on bundle size, this will inevitably happen.

smichel17 · 6 years ago
I can second this. I'm working on two projects, one paid and one volunteer. One is using vanilla css/html (requirement to work without js) and the other is using react. Doesn't matter which is which.

To set the context for the following statement, I've discovered that I prefer developing the nojs site. This mainly comes down to all the things that the browser does for me, but I have to handle manually in React, but it also includes something fun about figuring out the right css selectors to accomplish pseudo-interactivity without js. The point here is that I'm not personally inclined to avoid css.

And yet, when I work in react, I find myself writing less css, and the css I do write is closer to utility classes, something I never used in the nojs project.

I'm writing this on mobile but it's getting too long, posting and will move to desktop and edit in the reasons why I think React pushes me in the direction.

e: got here just as the edit window is closing, will reply to self instead.

madeofpalk · 6 years ago
I cannot see how react encourages you to forget :hover in CSS.
coffeefirst · 6 years ago
Yeah, those are choices. You still have to understand what you're actually doing in the browser and the DOM, same as jquery or vanilla js.

I can see how easy it would be to accidentally get a bonkers js bundle if you start using external dependencies without monitoring how much code they ship.

Does React have a perf cost? Absolutely. But there's something else going on here.

piranha · 6 years ago
The thing is that your tools should be making good this easier than bad things. And React is the opposite of that.
tnova · 6 years ago
So youb are saying that React makes it easier to do bad things than good things? Would you mind extending on that?
swyx · 6 years ago
they were using handrolled SSR in clojurescript, I'm not sure they set up code splitting.
capableweb · 6 years ago
> I'm not sure they set up code splitting

Don't think that matters. I've written (from scratch and inherited) and deployed many ClojureScript frontends, from one page ones with lots of interactivity to 30+ pages/sections, none of them reaching the size of 2.5MB minified (when using the production settings for Closure Compiler). Add in SSR and/or code splitting and the weight should be nowhere near there, leading to the guess that something is wrong in their config or they are embedding binary files into the JS asset.

phaedryx · 6 years ago
We were recently looking at https://ant.design/ which is one of the most popular React component frameworks. The components are nice and the design is appealing, but the 1.2 MB size is off-putting (https://bundlephobia.com/result?p=antd@4.5.3).

"Wait," we told ourselves. "Surely, we can do some tree-shaking, replace momentjs, be strategic in our imports and shave a ton of that off"

With all of that we got it down to 1/2 of the size, but that was still too big for our needs.

1f60c · 6 years ago
> dead-tree elimination

The practice of removing unneeded code from a bundle using static analysis is commonly known as “tree-shaking”, but I like your version better. :D

Izkata · 6 years ago
Looks like "dead code elimination" is what this is generally called in compiler-land - another thing rediscovered in javascript-land and given its own name.
rmrfrmrf · 6 years ago
> This is some strange reasoning that I have yet to seen myself. If you can do the hovers states/drop down menus in CSS, why not do them in CSS, even if you're using React?

Because when requirements change and your hover animation needs some additional flare to it in certain cases, you'll be glad that you had automated unit tests to verify original behavior still works along with your customizations.

traveler01 · 6 years ago
> This is some strange reasoning that I have yet to seen myself. If you can do the hovers states/drop down menus in CSS, why not do them in CSS, even if you're using React? Seems to be blaming something on a library that the library has no care about in the first place (which to be frank, seems relatively common in web dev circles).

Let's all be honest, that's complete laziness or lack of knowledge by the developer.

> And holy guacamoly, how do you end up with this?! Seems that something was surely wrong in the compilation options, forgetting to mangle names or something, missing dead-tree elimination maybe?

Maybe sourcemapping?

brainless · 6 years ago
I have been with React for 4 years now. Link state can be driven through React if you are testing some state or URL (active URL). But hover should never be React driven. I can not fathom why anyone would do that.
richthegeek · 6 years ago
The first legit reason I can think of is if you have a particularly complex UI with fixed/absolute/sticky positioning and you need tooltips. In this case, CSS gets in the way and you need to render the tooltip through a tooltip and so need to set the position using JS on hover.
Olreich · 6 years ago
The framework and libraries and information you find on the internet definitely encourages you to go for animations via JS. Might be a holdover from before CSS3, but I'm not sure I've ever seen people really try to use CSS3 for their animations unless people were working on their own toys. Just google "animated X react" and 80-90% of the articles are massive JS components with a little styling in the CSS.

For size of the bundle, just remember the node_modules black hole meme. The amount and size of JS libraries is no joke, it's wildly out of control. 2.5MB minified non-gzipped is common mostly because of a paradigm of "once you gzip it it will be small, and inflating that doesn't cost anything, and this way everything is preloaded!". Libraries come with a bunch of images embedded as Base64 encoded strings, the full localization tables, 40 1kb depedencies (left pad and friends), etc. etc. etc. These are all the default and no one changes defaults.

To make a reasonable web application today without all the insanity, you have to be very disciplined, because everything is pointing you toward doing dumb or crazy things.

hliyan · 6 years ago
When I first read the haiku at the bottom of the HTMX homepage, I had a flash of insight.

javascript fatigue:

longing for a hypertext

already in hand

What are we doing? State management libraries? Hypermedia is the engine of application state. Send data to client as HTML and have the client apply styles over it, rather than converting from JSON to local objects and storing in some sort of reactive data store. You will find that semantically structured HTML is almost as economical as JSON.

hinkley · 6 years ago
The Zen of jQuery moment for me was realizing that many of our bugs came from trying to separate the source of authority from the system of record.

It was a tremendous amount of busy work keeping metadata about DOM elements stored separately from the DOM elements, and hanging the values off the element was so much simpler in initial implementation, maintenance, and exploring other people's code.

Everyone was so excited about the virtual DOM in React 'n friends, whereas I saw both the functionality and the excitement as warning signs that I should stay away. I hoped this would turn out to be a fad, but it's a little long in the tooth for that scenario to play out now. For a while I watched news articles for the chinks in its armor, these days I'm more focused on other tools that satisfy niches, and wondering what will end up being the 'CSS3/ES6' moment for React where the browser does 20% of the work to have 80% feature parity with React.

hunterloftis · 6 years ago
I think you may be interested in Web Components.

https://developer.mozilla.org/en-US/docs/Web/Web_Components

kungato · 6 years ago
Why does is handling state on the backend better than handling it on the frontend? You will always have the cost of waiting for the server to return the full html every time you want something to happend and still you will have cases where you are handling state on the frontend
ricardobeat · 6 years ago
> return the full html every time

The post mentions their HTML size decreased - most likely due to reduction in intermediate components and nesting.

Note that with an SPA you need to send templates (in the js bundle) + data (json api) to the client, which by definition will be at least as large as static HTML for the same content: HTML is nothing more than the template and content already baked in. In practice the JS templates are much larger due to containing the entire application logic + compiler overhead.

Finally, the benefit of having the templates already loaded is only realized over longer timespans, when probably half of your users are coming in with an empty cache anyway.

tluyben2 · 6 years ago
I have not seen a good case of this. Can you point out one? Managing state on the server is trivial; sessions and database and that is it. How does handling on the client work? Well it works if you double up on the server; it is a crime when there is some SPA that manages state client side; something goes wrong and it is stuck, press reload, state gone; login page. It is annoying to me as dev, it is creating serious anger for people who do not understand this. They press f5 and are logged out. Wtf. Or their shopping cart is now empty. So if you want to fix that you have to handle state on the client and then sync with the server; how is that better than just having it on the server? I am a backend dev but I see more and more of my frontend colleagues move stuff to the server: it is just easier to reason about imho.

Sending over generated pieces of html that update divs I find a quite nice compromise: not the complexity while having updates without refresh. Intercooler sounds like that.

hliyan · 6 years ago
Theoretically, you have a point. Practically, you are reading this comment on a website that not only does exactly this, but refreshes the entire page (rather than a small block of HTML, intercooler-style). The performance benefits are evident.
lr4444lr · 6 years ago
Because the user can't be trusted - on several levels.

Deleted Comment

hestefisk · 6 years ago
Agree, this is so true. I will give it a few years before we are all back on server rendered web apps.
SquareWheel · 6 years ago
Server-rendered web apps never went away. They are still extremely popular. The tech stacks have only diversified.
kome · 6 years ago
you are SO right... but web developers have decided to go for complexity over simplicity and elegance.

IMHO this happened just because complexity and fads generate so much more money, in the long run.

arethuza · 6 years ago
It would help if there was some objective way of measuring "elegance" in software.

Some people think hammer factory factories are elegant.... ;-)

onion2k · 6 years ago
We need to look at it from two sides: if it’s good for developers and if it’s good for users. React was great at former and terrible at later.

React is not "bad for users". Developers build complex, fast apps with React all the time. It can be fast, but if you make mistakes with it then it's easy to make something very, very slow.

The app I work on is huge. It's ~8MB of uncompressed React + Redux in development (much smaller in production though), and pages include a lot of assets so they can weigh in at 23MB in the worst cases. A complex page can have up to 60,000 DOM nodes under React's control with thousands of event listeners. It starts in about 3s and never drops below 60fps.

lgl · 6 years ago
> A complex page can have up to 60,000 DOM nodes under React's control with thousands of event listeners. It starts in about 3s and never drops below 60fps

Can one really make such affirmations regarding client rendered web apps? I'm assuming these numbers aren't solely measured on localhost in some state of the art development machine/device so won't it depend on the client's machine specs, browser, usage, bandwidth, etc?

schwartzworld · 6 years ago
I don't know what bandwidth has to do with react managing the DOM.
krzepah · 6 years ago
This is how i manage more than 60,000 DOM nodes https://github.com/developit/preact-virtual-list ; actually i think i could handle 600,000 and still have no problem.
Davertron · 6 years ago
This is admittedly nit-picky, but you're not managing 60k DOM nodes if you're using a virtual list, that's the whole point of virtualization. You might have 60k items in your list but you're only ever rendering a tiny subset of those items based on what is visible (with some overlap).
onion2k · 6 years ago
It's not virtualized. It's not even a list. It's a very large SVG with lots of foreignObject bits in it. The app is a diagramming tool - imagine Visio but for lawyers to map out contracts and ownerships between hundreds of corporations.

Deleted Comment

Dead Comment

astura · 6 years ago
Can you share a link to a react app that is both complex and fast?
swyx · 6 years ago
> we’ve discovered that React also leads to some questionable practices. Like hovers in JS (rather than in CSS), drop-down menus in JS, not rendering hidden (under a hover) text (Google won’t be happy), weird complex logic (since it’s possible!), etc. You can have a React app without those problems, but apparently, you have to have better self-control than we had (nobody’s perfect!).

idk if this is fair. OP was using some pretty niche tools (clojure) whereas best practice React metaframeworks like Nextjs may have addressed some of those pagespeed issues.

additionally, I highly doubt that the author has replicated this functionality by using his new turbolinky framework.

So the post is better titled "I improved webpage speed by throwing away React AND a bunch of UI requirements". which is fair dinkum, but less exciting.

piranha · 6 years ago
> additionally, I highly doubt that the author has replicated this functionality by using his new turbolinky framework.

Which functionality?

> a bunch of UI requirements

So your point is that you don't really know, but let's blame them for trying, or what?

vezycash · 6 years ago
It's hard but take a few minutes off before responding to snarky comments.

Please answer their indirect question: "Did you replicate every of the react app's functionality in the app?"

yowlingcat · 6 years ago
> So your point is that you don't really know, but let's blame them for trying, or what?

I think GP's post is that _you_ don't really know the landscape which was why you reinvented the wheel, which I tend to agree with. You even agree with this unless you're being rhetorical here, no?

> Which functionality?

Let's take a look at every feature we see on the next.js page (https://nextjs.org/):

Zero Config Automatic compilation and bundling. Optimized for production from the start.

Hybrid: SSG and SSR Pre-render pages at build time (SSG) or request time (SSR) in a single project.

Incremental Static Generation Add and update statically pre-rendered pages incrementally after build time.

TypeScript Support Automatic TypeScript configuration and compilation.

Fast Refresh Fast, reliable live-editing experience, as proven at Facebook scale.

File-system Routing Every component in the pages directory becomes a route.

API Routes Optionally create API endpoints to provide backend functionality.

Built-in CSS Support Create component-level styles with CSS modules. Built-in Sass support.

Code-splitting and Bundling Optimized bundle splitting algorithm created by the Google Chrome team.

Now, do you want some or any of these things? How long do you think it will take to incorporate them into your new tool which you just rolled from scratch?

I guess at this point I'll add in some opinionated views here. At a certain point along your software engineer journey towards becoming a senior engineer, you are supposed to understand that undifferentiated heavy lifting and implementation is a bad strategic move in terms of technical strategy. If I am your CTO and you are telling me that you want to write your own Intercooler-esque library and move all of our core frontend checkout code away from React (an ecosystem with conventions that much of the rest of the world uses) and towards a proprietary solution I am going to ask you for a good reason. That is to say, I am unlikely to be persuaded by "I didn't spend enough time deeply researching how the rest of the ecosystem's users handle these issues" and I am likely to gently remind you that we will likely get more mileage out of investments that make our user experience better rather than scratching the itch to write a new framework.

mercer · 6 years ago
As others have commented, this doesn't seem like it's React's fault.

But it does illustrate how React isn't a magical solution to the front-end woes and how complicated the whole thing still is to do right.

I'd still use React for projects, but for now I've been incredibly happy with the LiveView solution that Phoenix/Elixir offers (or the variants for other frameworks. Blazor for C#, LightWire for Laravel/PHP?).

It's surprising how often I'll work on something and realize that the solution is quite simple now, where before it would definitely mean some serious thinking.

For example: libraries. I remember so many projects where I needed do do some date formatting or manipulation. Moment.js was the obvious solution, but including the whole library was not an option.

With LiveView I can just pull in whatever dependency I want, because it's all server-side. It's only the markup diff for the specific component that gets sent down the wire.

Or security. I need to show a user, but only a 'friend' can see the email address (or other profile details). The 'old-fashioned' way would involve separate API calls and a certain nervousness that perhaps I might end up in a situation where the front-end behaves how I expect, but the API calls somehow expose non-friend data.

With LiveView I can just add a conditional statement to the view, and since the resulting HTML is all that does to the client, I'm done!

Of course this only works with a persistent and relatively low-latency connection, but I can't remember the last time I worked on a project where this wasn't an implicit assumption.

I'm perfectly happy using React/Next/Vue when necessary, but it's a really strange experience to read these kinds of articles and threads these days when for so much of my day to day these problems just went away.

piranha · 6 years ago
LiveView is also very interesting. The main reason we went other way is that amount of connections and state held on server will be really high, plus we have some clients with bad connections and regular HTTP works much better on those than websockets.
emerongi · 6 years ago
LiveView can use HTTP longpolling.