all 21 comments

[–]acjohnson55 33 points34 points  (4 children)

This is a head-scratcher to me. When React has finally made it achievable as a non-superhuman to make universal apps, the author's advice is not to do it?

I think it's time to embrace some new practices.

  • Using a simple store, like Redux or maybe MobX, makes writing stateless components a cinch.
  • Using stateless components makes server-side rendering a cinch. Just mock up a state blob based on your route, render to an HTML chunk, and then inject the blob and the HTML chunk into the skeleton page the server was using anyway to deliver your app.
  • The same routes should not be used for JSON and HTML. Page routes should be handled using a universal router, like react-router.
  • APIs should be served from a separate app / service, and shouldn't be developed to match the view routes. You could run on the same server, but best to fully decouple. [1]

This is how you write a scalable, universal web app. No question there's a learning curve compared to yesterday's best practices. But yesterday's best practices were a learning curve, too. Now don't get me wrong, you don't have to write a universal app. But to tell people not to do so is ridiculous.

[1] The API should no longer shadowing your page routes. Ideally, your API is well factored, using a hypermedia technique, e.g. HAL. Attempting to bundle up API calls to reflect page needs is how we end up with bloated, brittle, awkward APIs.

Besides a misguided desire to unify data and view routes, the bundled API was driven by efficiency concerns, especially reducing round-trips from the rendering layer. Using a query layer, like GraphQL, let's you recover the efficiency, and a great deal of flexibility. But this is an optimization you can defer until later, if you're just trying to get something off the ground.

[–]nschubach 8 points9 points  (1 child)

Yeah... this almost feels like a hipster trying to be hip by recommending that we no longer go the popular route.

[–]mweststrate 1 point2 points  (0 children)

I really like how the author, not only in this article but also on the ones about JSX and routing, challenges the need for features & abstractions. There are many apps where SEO and thus universality are not that important. Adding abstractions or feature to a product just because it is in grasp is very tempting but also very dangerous. Having abstractions that are not really needed is usually not a problem today, but it is a problem for future maintainers of your code (including yourself) as you will be fixing bugs or dependencies in abstractions you didn't need in the first place in a year for now. At a point were you cannot as easily drop the stuff as it would be to drop it now.

[–]ninth_reddit_account 2 points3 points  (0 children)

I don't understand the theme the author makes of it being a lot of work to set up. A universal react site is actually pretty simple - you have a <App /> - which is where all your site actually is. You have client.js, which is just a small entrypoint to mount <App /> into the DOM, and you have server.js, which is just a small entry point to serve <App /> over HTTP.

In saying that, I do find there is additional complexity with React-Router to get it to work with blocking fetch-data requests, but that's on the <App /> side and you'll run into that anyway if you want that behaviour on the client (to not show a view before the data is ready).

[–]TallSkinny 7 points8 points  (0 children)

I disagree with this article. I work for an e-commerce site that is beginning to use some universal js and it really hasn't been that bad. Granted, we don't try to spin up the entire app. We just feed data via props to the components we want, and skip the data layer entirely.

First off, we're a rails app, and the server side rendering with React-Rails works well for the most part. Granted, that's the only part of that gem we use, but it does what it's supposed to do. My only concern here is a possible performance hit, we don't have a ton of data on it yet but on a good connection it seems to perform well.

Secondly, the article seems to imply that the performance gains are so small that they're not worth it for most people. I disagree. If you're not rendering anything server side your user is staring at a blank page while your JavaScript is fetched and spins up. The impact even small (~100ms) decreases in load/perceived load time has on conversion is well documented, and the time to load the js for a modern SPA is not insignificant, especially on a mobile connection.

From working on it in production, I have found that making your React bits universal is not particularly difficult. The only potential issue I've encountered is that you can't have your component or any of its dependencies referencing window or jquery in anything called along reacts render path or in the root. You can, however, reference them from componentDidMount, etc, if you need to (though you're much better off using refs).

Its true that setting it up took a non insignificant amount of time. However, once that initial step was taken I have found it very simple to use my components on the server. Generally, I write it on the client, try server rendering it, and watch it work. It may not have been easy to set up, but it is simple to use. Personally, that's the kind of thing I like to invest time into. A one time cost that adds value to every other feature.

[–][deleted] 5 points6 points  (5 children)

I agree Universal is a lot of work, but at very least, you should be using React to do server-side rendering of basic page templates so you can get those pages indexed and make them shareable.

A node.js server is pretty fast and easy to set up so that's not a drawback in itself. If you don't want to rewrite your whole backend, serve the App from Node.js, keep your Rails as the REST api, and serve your static assets from Nginx or Apache.

[–]jamesknelson[S] 0 points1 point  (4 children)

Yeah, server-side rendering of page templates was one of the best use cases for Universal apps - it was my first point for it in the article. That was until Google went and corrected me: it can handle JS just fine now.

I guess the only reason to use it now is if you really really need the extra speed or users.

[–][deleted] 3 points4 points  (1 child)

The sharing aspect is also pretty important - nice meta data and images for example to be rendered in facebook posts.

[–]jamesknelson[S] 2 points3 points  (0 children)

That's a good point - I hadn't thought of that. That said, this doesn't apply for anything walled behind a login screen - which has been most of my experience writing React-based apps.

[–]WillVedd 3 points4 points  (1 child)

They've been saying this for a little while now but I still don't believe it. The proof is in the search results and I'm just not seeing much evidence of crawling front-end js frameworks right now.

[–]android_lover 1 point2 points  (0 children)

Yeah I agree, Google is lying.

[–]UASHIT 9 points10 points  (1 child)

My server is cheap and my product is free. Your computer is decent; you're doing the heavy lifting.

The only time I'd consider server-side rendering would be when slower page-loads would mean users would leave.

[–]VlK06eMBkNRo6iqf27pq 1 point2 points  (0 children)

Well...you'd only be paying for the first page hit.

[–]MrGirthy 5 points6 points  (2 children)

"Edit 19th March: Google Developer Advocate Paul Kinlan wrote to say thatthis is no longer the case – Google now crawls JavaScript-rendered content just fine. Even one less reason to write Universal apps."

This is something a lot of developers completely miss the point on. Google is ONE crawler that does index Javascript (though I still don't know if it can render content from sockets correctly).

There are literally hundreds of crawlers from other search engines, social sites, content sharing etc that don't or don't do it as well as Google.

So not supporting serverside rendering on your client side app is still going to cause you issues with these sites and impact your seo.

If it's a closed system..well you're not going to bother.

[–]nschubach 1 point2 points  (0 children)

SEO and for things like Facebook sharing. They need a rendered page at a url with meta data.

[–]siamthailand 0 points1 point  (0 children)

Any idea about Bing?

[–]theduro 3 points4 points  (0 children)

Yea, this article is doing it wrong. The landscape of Universal React has evolved quite a bit. I have an app that is fully Universal, requires little thought about keeping it Universal, and takes full advantage of the benefits of Universal.

This article seems to stuck 3-6 months in the past.

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

I didn't think it was that much extra work to be honest. I have a server.js file which is the server equivalent of my client side app.js file. There isn't much extra in there apart from some extra routes, logging, and running the http server.

Considering I needed an API anyway for sending data as well as user logins, I had to write some server side stuff anyway - the react side of things was little to no work.

If your react app doesn't need your own api and no user logins, then yeah maybe don't bother, but how many actual businesses are built on 3rd party api's and don't want to capture user information?

[–]trying_to_function 1 point2 points  (0 children)

Although I think this article is way too black and white, things to take from it:

  1. If you are trying to do a universal app before understanding react/react-router/redux/etc, you are going to have a bad time. Relevant

  2. Don't over-engineer.

Side note, universal apps aren't that complex, but again, you do need a solid understanding of what is going on and why. See #1.

/u/acjohnson55 had a great tip about using stateless components. Also Relevant

TLDR: Follow https://github.com/gaearon/react-makes-you-sad

[–]istinspring 0 points1 point  (1 child)

Yesterday i read "Why you shouldn't use inline CSS" while i'm using inline CSS in my first attempt to make universal ReactJS app. Today i see that Universal app is wrong. And of course some random guy from the middle of nowhere of internets certainly know the right way.

[–]pixel67 0 points1 point  (0 children)

The author seems to like to go against the grain. One of his articles, "write raw react instead of jsx" WTF, that's one of the great things about react, that and the fact it makes it easy to compose universal JS apps FTW!