Flux is like a framework for frameworks – frameworkception, as one redditor put it. There are as many implementations as there are opinions, all with their own strengths and weaknesses, and none of them with authority.
Wait, is it really that simple? Yes, it really is! But since you’re still reading, you’re probably not someone who is easily convinced. And that’s why I’ve prepared this comparison for you:
- Community: Will you regret choosing the implementation if the maintainer gets hit by a bus?
- Simplicity: Simpler code generally results in a shorter learning curve and easier maintenance. However, too much magic can make things confusing.
- Functionality: Does this Flux implementation actually provide Flux-like features, including debuggability and easy handling of async data?
- Documentation: No matter how great the functionality is, it is no good if you can’t figure out how to use it.
There are a lot of flux implementations – possibly hundreds – and so we need a way to narrow down the field. Luckily, our community criteria allows us to do just that.
If Facebook both invented Flux and provide a Flux repository, you may be wondering why we’re having this conversation at all?
Somewhat surprisingly, Facebook itself uses multiple implementations internally. This indicates that Facebook’s Flux repository is not meant as a canonical implementation. Supporting this is the fact that until recently, Facebook only provided an implementation of the flux Dispatcher, with stores, actions and containers left as an exercise to the reader.
Given that this project is where Flux started, it is no surprise that it has a large following in the community. In fact, Facebook’s
Dispatcher is used in a number of alternative Flux implementations – so it isn’t going to be disappearing any time soon. As a bonus, Facebook’s Dispatcher is the same one they use in production.
Facebook recently expanded their Flux repository with tools to ease the implementation of stores and containers. However, the simplicity comes at a cost: you still can’t get started without a significant amount of boilerplate.
Given that this is the original Flux implementation, you may think that it would be the embodiment of Fluxiness. But while it does facilitate writing a Fluxy application, it still leaves a lot to the imagination. For example – Facebook’s Flux doesn’t provide any tools to work with action creators. Additionally, you may find yourself stuck when you need to handle async data.
Flux’s documentation is a little thin. Given enough time, it’ll certainly teach you what you need to know — but it can be a little hard to grasp for beginners. It can also be hard to distinguish between documentation for Flux as a pattern, and for Facebook’s implementation.
Reflux is one of the older Flux implementations, with its first commit being checked in on the 2nd of July, 2014. As such, it didn’t benefit from the hindsight that a number of newer implementations have.
Reflux advertises itself as “A simple library for unidirectional dataflow architecture inspired by ReactJS Flux.”
Being one of the first Flux implementations, Reflux has grown a sizeable community, with almost 4000 stars on GitHub. But while size does matter, its growth has ground to a halt in recent months.
Reflux initially feels a lot simpler than Flux. It achieves this by merging Flux’s
Dispatcher with its action objects and action creator functions, creating the new concept of action functions. This simplifies your code by eliminating Flux’s enormous
switch statements and singleton
Dispatcher. It also makes actions a lot easier to create.
But while actions may feel simpler, Reflux replaces
waitFor with two new concepts: joins and aggregate data stores. And despite spending a lot of time reading Reflux’s code, I still don’t understand them.
While Reflux’s action functions may feel simpler than Flux’s action creators, they come at the expense of functionality. The most obvious manifestation of this is how Reflux complicates the process of dispatching multiple actions at a time – a pattern which is often used with async code. Additionally, the lack of a central Dispatcher makes it difficult to log, inspect and replay user actions — eliminating Flux’s debugging benefits.
Reflux has a reasonably comprehensive README. Unfortunately, if the information you need isn’t in the README, you’re going to have trouble googling for it amongst all the information on Acid Reflux.
Alt — like Reflux — places emphasis on terseness. Unlike Reflux, it still places emphasis on being Flux.
Alt has a smaller community than the two implementations we’ve already looked at. However, despite the smaller community, it has almost twice as many Pull Requests as Reflux.
The thing that struck me during my research is that it feels like the people who like Alt really like Alt. Even if the community is small, I can’t see it disappearing anytime soon.
Alt feels simple. There are two reasons for this:
- Alt’s API has been designed around ES6, and supports ES7 decorators. As a result, Alt-based apps look pretty (to my ES7-trained eyes).
- Alt merges Flux’s action creators and action objects into action functions. However, unlike Reflux, it still makes use of Flux’s
Alt provides you with most of the benefit of Flux, but with a nicer syntax. The only caveat is that if you want meaningful logs in production, you’ll need to ensure that action function names aren’t mangled by your minifier.
Alt’s documentation is excellent. I wish I had access to Alt’s documentation when I was learning Flux.
With its first commit dated May this year, Redux is the new kid on the block. But despite this, it now seems more popular than Flux itself.
An interesting piece of trivia about Redux: A number of people will tell you that it isn’t actually Flux. Not that it really matters, given it solves the same problems.
Redux’s README starts with this quote from Bill Fisher, one of Flux’s creators:
I asked for comments on Redux in FB’s internal JS discussion group, and it was universally praised. Really awesome work.
Redux is by far the simplest of the frameworks I’ve discussed. It achieves this by making additional assumptions beyond those of Flux itself. Chief amongst these is the assumption that you never mutate your data. With this knowledge, you no longer need the Flux
Dispatcher. It also makes it possible to describe changes to your data with plain old functions instead of a giant
The brilliance of Redux is that while it is in many ways simpler than Flux, it doesn’t lose out on any of the functionality.
Action objects are still created with action creators. You still have a central
store object which allows you to inspect and debug user input. And with the help of redux-thunk, it is still possible to dispatch multiple actions from one action creator.
But while the community, simplicity and functionality of Redux are worth getting excited about, the documentation is bloody amazing.
And the winner of the award for the most simple, well documented Flux implementation with the largest community is … Alt! But why limit ourselves to Flux?
The motivation behind Flux is to simplify our application architecture, making it easier to reason about and maintain. And unless you have a really unusual use case, Redux is currently the best way to achieve this.
Of course, knowing how to structure your application’s data is only half the battle. What about structuring your CSS, your build system and your routes?