8 ms·
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
by kilburn 6y 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 6y agoIt'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.
- deleted 6y ago[deleted]
- gvjddbnvdrbv 6y 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.
- ralls_ebfe 6y agoWhy can't the server-side template rendering code consume an api as much as frontend JavaScript can? I don't see any reason for this to happen in the browser.
- unethical_ban 6y agoThe first time I got even close to a custom web page (internal request system for our team), the devs did this. They wrote it as two Bottle (python) applications: One was the API for the app, the other was the delivery of the Javascript to the client, which called the API.
- bernawil 6y agothe template rendering lives side by side with the controllers, why would it make an api call? But something similar but not the same as that was the norm during the jquery era before the early js frameworks arised (backbone, ember et all). You had your full-stack server-side MVC framework render initial views and from there the js would pick up and all UI interactivity would be ajax calls to the restful(ish) api. It was pretty terrible.
- piranha 6y ago> why would it make an api call Because this introduces clear separation of concerns? You don't need to make this API call via HTTP, you can just call a function. You don't even need to generate/parse JSON! I know that because this is what we are doing. Just calling a function called "httpapp". :)
- beaker52 6y agoWow, 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 6y agoWhen 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 https://rebassjs.org/box and resize the page back and forth
- cityzen 6y agoKind 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.
- nprateem 6y agoOver 10 years ago with various ORMs.
- RandoHolmes 6y agothink 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.
- WorldMaker 6y agoThere's an interesting correspondence with water and data going even further back than that in the English language, think about how often you hear variations on "learning through osmosis" or "hopefully I will pick that up through osmosis". Osmosis is specifically diffusion of water. It's fascinating that so many speakers of English refer to it as "learning through osmosis" rather than the more accurate and less water-centric "diffusive learning". I've no idea of the etymology for this or why this conflation is surprisingly so deep in contemporary English culture, I've just been fascinated by it for a long time.
- chias 6y agoNot sure diffusion is really more accurate than osmosis. It does need to diffuse across the brain membrane, after all ;)
- WorldMaker 6y agoWell, one can assume the eyeballs are akin to an aqueous membrane, but the human ears generally should be non-aqueous for best results. ;)
- city41 6y agoReact 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 6y 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.
- davidwparker 6y agoIf 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 6y agoThere 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.
- nawgz 6y ago>Flexbox won't work because you don't have a fixed height Are you saying the issue is that flexbox will force everything to have the same height? I am relatively sure that `flex: 0 0 fit-content;` on the children and `flex-wrap: wrap; flex-direction: column;` on the parent will do what you want
- kbenson 6y agoI 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 6y agohydrate [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 https://reactjs.org/docs/react-dom.html#hydrate [2] https://reactjs.org/docs/react-dom.html#render https://reactjs.org/docs/react-dom.html#render
- kbenson 6y agoThanks, and yeah, I got most of that from some Googling around afterwards, but I do want to note that I had encountered your first link, and that it itself is somewhat recursively defined with terminology that is glossed over: ReactDOM.hydrate(element, container[, callback]) Same as render(), but is used to hydrate a container whose HTML contents were rendered by ReactDOMServer. React will attempt to attach event listeners to the existing markup. Searching for hydrate in the React docs leads you to the hydrate method, which describes itself in terms of its use to hydrate a container. The crazy thing is that there's numerous blog posts that purport to tell you what react hydration is, which do the exact same thing and define it in terms of itself. Partly, this may be React (and the community's) reliance on you knowing what that concept is, but that's particularly unacceptable in article that purport to explain it. Is it really so hard for these reference docs and explanatory sources to say something along the lines of "hydration in React is the act of fleshing out a server delivered model of the page that came with poor or no data with rich data delivered later in the process" ?
- bmarkovic 6y agoI'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.
- aabhay 6y agoVue’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.
- kilburn 6y 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/ 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 https://nuxtjs.org/guides/get-started/installation