Low Overhead React

25 May 2019

“React. Write reusable components. Make your data flow one way. Never directly use the DOM again.” There’s a lot of benefits that a developer gets by using React.

But React is easy to make complex. It’s so very tempting to optimize early. There are a lot of decisions left to you on how to architecture your web app.

The techniques listed here will often make your React app have less work to do, and therefore run faster. Implicit performance is a benefit if it means less time later adding optimizations to claw back to a fast experience.

But the primary aim is to make your app easier to write, easier to change, and easier to debug. Less overhead for the person maintaining the code. Writing low overhead React means you can more easily focus on creating that great experience for your users, while not sacrificing the developer experience.

Low Overhead React Principles

  1. Don’t abandon CSS
  2. Choose packages carefully
  3. Ensure every component does at least one thing well
  4. Don’t let every component talk with the world
  5. Don’t attempt to optimize React rendering too early

Don’t abandon CSS

Look, CSS (or SCSS) has its limitations. JavaScript is obviously more capable as a language. But CSS is proven for its task. It is fast. It can declaratively handle focus and active and hover states, and it can handle a variety of media queries. It just works with server rendering, and is interoperable with technology choices other than React.

Use CSS variables to create reusable styles for typography, spacing, colors, and other things that are consistent across components.

html {
  --link-color: orange;
}

main a {
  color: var(--link-color);
}

You override CSS variables when rendering by using the style prop:

<article style={{ "--link-color": "purple" }}>
  …
</article>

(You can see an example like the above here: https://codesandbox.io/s/react-css-variables-chbsj)

CSS is still evolving. The standards are adding more capabilities. There are new approaches to organizing and reusability. Not to mention layout.

If you use CSS-in-JS, it doesn’t mean you are banned from using standalone CSS. Base CSS files work great for reusable styles across components.

Choose packages carefully

I’ll be honest: there are a lot of heavy packages out there. Calendars. Themeable kits that come with every UI control you can imagine. State and data structure libraries. Many of these dependencies have a big impact on the bundle size, and therefore the time your users will spend waiting for your application.

This doesn’t mean stay from them. Use some, but don’t just add all your first choices. Don’t say yes unless it really provides key value. A package that makes your experience better as a developer (let the team finish faster!) might make your users’ experience worse (let the user start slower!).

Yes, tree shaking can help improve the initial load time, but if you have large packages that you use as the foundation of your app, most of the tree will remain not matter how hard you shake it. And if the shaken out parts are soon downloaded after anyway, you might be consuming a lot of your users’ limited data. We don’t need to pretend NPM doesn’t exist. But we do need to remember that every npm add is also often adding wait time for every user.

Ensure every component does at least one thing well

Presentation vs Controller. Smart vs Dumb. Connected vs Reusable. Organism vs Molecule. There’s many way of categorizing and splitting-up components into specific roles. I’m not going to offer an opinion here because many ways work well. What I am going to ask is to make sure every component has a role it does particularly well.

You might decide this means the single responsibility principle, so that a component can only be purely HTML focused, or purely subscriber focused, or purely Redux connect focused, or purely analytics focused, etc etc. I leave that up to you, because there often is value in a component doing multiple things. If a component is a function, then it serve to reason that it can be made out of multiple other functions, and these functions can have a single responsibility.

All I request is that you ensure each component does at least one thing particularly well. For example: It’s great at producing markup. It’s great at talking to the rest of the app. It’s great at optimizing render times for this particular case. It may well do more, but at the least it is competent in some particular thing.

If it’s not doing a great job at anything in particular, if it’s trying to speak HTML and API and Redux and URL all at the same time, then it might be time to split it up. A dedicated smaller component can focus on a particular task and communicate its intent better. It’s often fine to keep it in the same file.

Don’t let every component talk with the world

A component is easiest to manage when it follows a simple contract: given some input, I will return what I want presented. Different input, different output. No other factors.

A slightly more complicated component contract is that: in addition, I will produce some side effects. I will POST to a server, I will talk to a local data store, I will add an event listener directly to the DOM.

Another more complicated variation is I will read from outside of my props. I will fetch from a server, I will subscribe to the latest changes to a local data store, I will listen to when the window changes size.

These components can get out hand. Many components start talking to many things. When hundreds of components have a direct connection with the local data store or communicate with the server. Or when the user resizes the window and many dozens of components individually want to update themselves.

I’m not advocating for a particular architecture or a particular number of communication points or set a limit to how many components are allowed to talk to the server. I’m saying be mindful of how many connections there are between components and their outside world. Otherwise a couple of simple changes in the outside world can schedule a huge amount of work.

This may not only lead to performance bottlenecks, but it will also make debugging and future changes harder. Which component made that change? If I rename or restructure this reducer, how many components had this knowledge and so will need to be updated? It’s best to make these questions easier to answer by reducing the surface area of connections.

Make smaller worlds for your components by bundling collaborators together, and then export a simpler component that will be used to hide the details and nuance inside. Add single connection points that bridge between one world and another. Add facades with small surface areas your components see, that then go and talk to the larger world, translating back and forth. Don’t just let any random component talk to whatever it likes. It might feel convenient now, but it’ll likely become inconvenient when changes are needed.

Don’t attempt to optimize React rendering too early

Don’t optimize your components until there’s a clear problem to be solved. React is designed so that straight forwardly written components will lead to great performance!

If do you want to apply optimizations, first read the documentation provided:

If it these don’t answer your question, then reach out to people from the React core team like Dan Abramov who happily answers people’s questions on Twitter.

Next, measure using the open source React DevTools which is available for Firefox and Chrome.

Measure the current profile by clicking record, performing the particular flow that you wish to make more performant, then stopping the record. Use the interactive charts to see the bottle necks and which components need attention.

Make changes, and profile again. It may take several iterations because your expected optimization technique might make things perform worse.

If you have existing optimizations like React.memo it might be worth removing all of these, and then using the React DevTools profiler to introduce them where you see a meaningful improvement.

Using React.memo relies on every prop passed to a component staying the same (being referentially equal) across renders to skip its own rendering. This can be infectious, leading to all your components having to follow this extra contract on your props. Trying to make everything referentially equal can be a lot more work that can lead to other performance overheads. And it’s very easy to pass just one prop that does not stay consistent, meaning the intended optimization is never applied.


React. It’s unique selling point is that it makes writing web apps easier. Yet it’s easy with React to find yourself battling complexity, or for users to be getting penalised performance. Being mindful about the overhead that some techniques and third party packages can bring helps keep complexity low, performance easy to find, and future changes maintainable.

Linked: The case of partial hydration (with Next and Preact)

22 May 2019

Lukas Bombach has written an article on partially hydrating server-rendered HTML so that less client code is needed. Hydrating becomes an opt-in process per top-level component. This is used to make a performant news site.

Now you end up sending your entire application code to your users including React components for every headline or text paragraph anywhere on your page. The result is an unnecessarily huge bundle that needs to be loaded, parsed and executed. This results in suboptimal performance, your page will be slow(er) especially for mobile users and for no good reason!

The issue with Gatsby is that it has to generate all of your pages and subpages at compile time which does not really work when you have sites linked to a CMS that updates everyday and that hosts millions of articles—which is exactly what we need for our news media sites. This is why we are using Next as well as modifying it to suit our needs.

The basic idea behind our version of partial hydration is: Instead of doing SSR and then sending your entire application to your client, only parts of your application’s JavaScript would be sent to the client to hydrate the parts of your website which specifically require JavaScript to work.

Typed Subatomic Styling: Part 2 — Comparison to Styled-Components

11 April 2019

CSS-in-JS is a popular approach to styling components within React apps. These libraries are much more sophisticated than simply inline styles. I chose one popular library, styled-components, to compare to the Subatomic CSS approach I detailed in my previous post. I look at the clarity of components, the amount of flexibility, and performance.

Read more…

Handy SPA config for Netlify

27 March 2019

Although Netlify out of the box won’t work with single page apps’ routing, it is easy to add. You can configure it to send all /* subpath requests to a single index.html file.

Steps for create-react-app

Here we will be using a create-react-app project. This should be easy to apply to other SPA toolkits.

Add a netlify.toml file to your src folder. In it write:

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

Edit your package.json file. Find the scripts section.

  “scripts”: {
    …
    "build": "react-scripts build”,
    …
  }

Replace the build rule with three:

    "build": "npm run build:react && npm run build:config",
    "build:react": "react-scripts build",
    "build:config": "cp src/netlify.toml build/netlify.toml",

This rule builds the static assets using create-react-app’s toolkit, then copies the netlify.toml file to this build directory.

That’s it! As long as Netlify is set to run npm run build then this will work. You will be able to visit subpaths and get the same index.html page served for all.

Typed Subatomic Styling: Part 1 — Benefits of TypeScript and CSS

16 March 2019

The benefits of components have been realized with systems such as React and VueJS. Styling these components has a number of approaches, from CSS classes written in SCSS, inline styles, and dynamically generated stylesheets via something like emotion.

Each styling approach has trade-offs in regards to reusability, performance, and developer experience. Also, special considerations often have to be made when doing server-side rendering.

In this post, we’ll explore TypeScript combined with functional CSS. I believe it offers big benefits over the other choices — it’s extremely reusable, fast, and offers a very pleasant developer experience.

Read more…