We set a goal for ourselves: build a prototype that can log into your Linode account via OAuth and list your Linodes, as well as a detail page. The idea is that we’d demonstrate several important things in the context of each framework:
- The OAuth flow
- Talking to the API
- Rendering to the DOM
For bonus points we could show off anything your framework did that was particularly cool, like hot module reloading. I made a React prototype, my colleagues Marques and Abe helped - Marques did the Angular 2 prototype, and Abe did the Mithril prototype. Eventually we presented our prototypes and recommendations to the rest of the development team.
Angular 2 & TypeScript
For those who want this more traditional object oriented model, Angular seems to be excellent. It has support for dependency injection and adding TypeScript brings a lot of value. It also provides a comprehensive framework that handles everything from routing to HTTP requests for you, with detailed documentation. However, for some of the more volatile features, Marques found the documentation confusing, incomplete, and inconsistent. This’ll probably cease to be an issue once Angular 2 is released properly.
Angular also offers some innovative ways of managing your data with the observables mechanic. They basically work like Unix pipes and let you chain operations together and subscribe to changes anywhere in the pipeline, then respond to those changes in your application. Angular is also well tested and the community has many examples, though some may be outdated (which is a problem for all three of the options we’re looking at today).
There are some disadvantages to Angular. Though Google has promised improvements to this, Angular 2 is pretty slow. There are lots of debugging things going on and the startup times are rough. The transition from Angular 1 to Angular 2 is also very jarring and those with preconceptions about how Angular works are going to have a hard time. Some people also criticize the “do everything” approach that Angular takes, preferring the Unix philosophy where tools and libraries with a smaller scope are composed to fill the full picture.
Mithril & ES5
Abe found that the deeper he got into it, though, the less effective it was. The documentation is lacking and it handles more complex situations poorly. He also called some criticism on its separation of concerns, noting that idiomatic Mithril models are aware of the DOM. ES5 is also a pretty bad language, which we’ve all known for a long time. Transpiling is the right call for your sanity.
I also asked Abe about the MVC pattern in general, and he still feels like it’s the right call in some situations. Abe worries that once your application gets big enough and cross dependencies start to pile up, MVC falls apart. Facebook feels the same way (though I think the prevailing thought is that Flux isn’t quite right, either).
React.js & ES6
design philosophy that most people are using with React these days. It takes
functional programming paradigms and introduces them to the web. The idea is
If you have a checkbox that toggles the visibility of foobar, it’s in your state
foobar: true. You then write your UI as a pure
function of your state. Given this
state, you return either
<input type="checkbox" /> or
checked="checked" />. When the checkbox is ticked, you create a new state that
has that boolean flipped and rerender your UI. Your entire application is
you can pass a state object into it and it returns what the DOM should be when
the application is in that state.
This sounds pretty radical to someone who is used to imperative programming instead of functional programming, like I was pre-React. An idiomatic React+Redux code base is not object oriented. Your code and your data are kept separate and you never mutate anything. This is one of the big drawbacks to React: it was much harder for me and my coworkers to grok it. By accepting this radical change to your development philosophy, you get some seriously awesome advantages. Your code is easier to reason about, more testable, and more consistent. It also enables some really cool things like time travel and hot reloading all of your code on the fly!
The downsides to React do exist, though. One of them is the documentation - it can be difficult to find the answers you’re looking for. React also showed up during the ES5 era and has struggled to move smoothly into the ES6 era. I get frustrated when I have to bind all of my functions in the constructor of my ES6 classes. Above all, though, the biggest pain point with React is setting up the damn codebase. Getting all of the pieces together and working the right way took me ages and was extremely painful. I’m also not a big fan of how big our dependency tree is.
Problems we ran into
Clarification on my praise of React/Redux/etc - it's great once you can get it set up and only if you never have to touch your build again— Drew DeVault (@SirCmpwn) May 17, 2016
I almost wrote the prototype from scratch. I originally used gearon’s Redux hot loader starter kit, which gives you the bare minimum necessary to get React and Redux hot loading in an application. We added the rest over time, and it has been a massive pain in the ass. We started with this:
- Redux reducers and actions
- Hot reloading
And we had to deal with all of this:
- Setting up and maintaining Webpack
- Babel 5->6 transition
- SCSS loading (and hot reloading)
- Getting tests to work
All of these things do not always play nice together. There are many versions of each of them and they’re all subtly broken and incompatible with each other. It literally took me 2 full days of work to switch from running tests on Mocha to running tests with Karma. If you value your sanity I highly suggest you just take our open source repository and repurpose it for your needs.