Vue vs React — Part 0: Thinning the Herd
In this series, I demonstrate some of the key development experience differences between using Vue and React to achieve the same outcomes.
Table of Contents
I was recently tasked with selecting a front end component library for the future of our product at work. I started with a list of options and quickly filtered it down to Vue and React.
Angular — Learning Curve
As is the case with any full-blown framework, Angular has a large learning curve. As I read over their docs, watched video tutorials, and compared equivalent code from other libraries, it took consistently longer to comprehend the Angular way. Perhaps this says more about me than it does about Angular, but it’s still the conclusion I reached.
Examples of additional complexity exist in app architecture, component definitions, and even template bindings. Perhaps one of the largest hangups for people not already familiar with it is Angular’s use of dependency injection.
For many devs, one of the reasons Angular is more difficult to learn than some alternatives is dependency injection. Generally speaking, when creating a module, that module is responsible for importing and consuming its own dependencies. However, Angular embraces a design pattern called “inversion of control” which makes the application responsible for injecting dependencies into child components.
The primary benefit of dependency injection is ease of testing — because you have control over what dependencies gets injected into your modules, you can easily pass mocks when testing. While admittedly valuable, this added convenience in testing comes at the cost of readable code. Under this model, components rely on dependencies they did not import provided to them by an extra layer of application logic. Requiring devs to embrace this design pattern in order to be productive is one of the things that makes Angular’ hard.
What if we could have the best of both worlds? What if we could write our components the industry-standard way where each component imports its own dependencies while also enjoying the testing benefits of dependency injection? Fortunately, Jest has us covered! Jest provides a means of intercepting
require statements and swapping them with mocks. It’s dependency injection that doesn’t require you to write your code differently. Here are a couple of demos.
Angular’s learning curve is higher in several places than I think it should be. A significant portion of that learning curve is mastering dependency injection and the additional application layer it requires. In my opinion, inversion of control is a cumbersome design pattern that makes up for itself by making your application testable. However, Jest allows me to write a testable codebase without having to bend to a cumbersome design pattern.
Due to concerns about download size, several issues with learning curve, and not wanting to go all in with a framework built around dependency injection, I opted to forego Angular.
Svelte and Stencil are truly innovative technologies.
Here’s the idea. You write your code in a clean, readable way, and Svelte/Stencil compiles it into something tiny, fast, and vanilla. Seriously, you can use these components with any framework or library. And it works extremely well! It takes the runtime you normally have to download and abstracts it away into a build step.
So what’s wrong with Svelte? One of the major considerations when taking a for-profit business into production is community. Are there pre-existing components? Are there docs? How big is the team that supports it? Will I be able to hire people who know it? Asking these questions helps you avoid risk.
The answers to most of these questions are not favorable enough to write an entire application using Svelte. A tiny example: Svelte doesn’t have its own router and doesn’t have a good virtual scroll implementation. Yes, I’m aware there are excellent off-the-shelf options such as PageJS and Navigo. But this at least demonstrates, on a small scale, that there isn’t a reliable first-party-maintained solution for some of the fundamental app building blocks out there — fundamental building blocks for which most ecosystems have first-party solutions.
The same issues apply to Stencil — it’s just not mature enough yet.
Now, ruling out using Svelte/Stencil for an entire application doesn’t mean we’ll rule them out for writing some of our individual components. In fact, using them for some of our more complex shareable components could insulate us from future change because their output is vanilla JS. Of course, doing so would require my team to learn a second new component library… We’ll cross that bridge when we get there.
In my opinion, Svelte and Stencil are not yet mature enough to risk using them for an entire application. We will likely evaluate using them for specific components when the time comes.
Preact — So You’re Telling Me There’s a Chance
Fast 3kB alternative to React with the same modern API. — Preact Docs
I’ve been using Preact in a personal project for over a year and I’ve really enjoyed it. With React still being on the table and Preact being so similar, it makes sense to at least try it out in the event we go with React. Here’s a list of differences between the two.
What’s good about Preact?
- Preact is one tenth the size of React. This improves bundle size and execution time.
- It’s API-compliant with React so you can use preact-compat to swap out React for Preact in an existing app and it Just Works™. It also allows you to enjoy React’s entire component library (mostly).
- Its CLI is great, providing a PWA with route-based code splitting out of the box. What’s more, you can configure its starting template yourself.
What’s bad about Preact?
- Preact follows React’s feature set. This means that it’s always behind React’s latest release.
- preact-compat doesn’t always work.
- Preact’s docs are sparse because they expect you to read React’s docs.
In theory, Preact is React with a smaller download and a faster runtime. It even has a couple of nice API changes like exposing
state as arguments to the
render method and allowing use of
class for styling (you can still use
If, by the end of this series, we decide to go with React, I’d like to give Preact a try. Doing so can keep our stack overhead as small as possible while theoretically still granting us access to React’s component ecosystem. And, if it doesn’t work out for whatever reason, the risk is small — converting it to React proper should take very little time.
Continue to Part 1: