A Year with React
In 2015 I spent the majority of my time working on React-based projects. Looking back I count seven apps I worked on:
- Three are in production serving people. The others were for learning purposes but a couple had production builds
- Three were worked on by teams of developers
- Two used Redux, one used Alt, the rest just React or a React and a pubsub/signals library
- Two had universal rendering
- Most had test suites
- All used webpack and babel bar the simplest throwaways
- All talked to a REST API. None of them were built on top of a traditional server-rendered app like Rails.
Here is a collection of thoughts.
Bootstrapping⌗
Echoing the thoughts of many towards the end of the year, the worst part of building React apps at the moment is the initial bootstrapping required. I would like to say I am much quicker at setting up a project now compared to January, but that is only somewhat true.
Every time I come to starting a new project an important piece has had its API changed: babel 5 -> babel 6, react-router 0.x -> 1, react-hot-reloader -> babel-plugin-react-transform… that involves a bit of hacking each time to get things working. Throw in universal rendering and it may take a couple days before it is ready for writing application code and tests.
An alternative to building from scratch is to start with a boilerplate.
The problem with boilerplates is that there are a ton of them. Granted a github search with multiple keywords is not the most accurate, but a search for ‘react boilerplate’ at the time of writing returns 1,514 results. ‘angular boilerplate’ returns 1,233 results and AngularJS has been around for more than three years longer than React.
Are they all more or less the same? This one supports universal rendering and this one does not. This one uses Radium and this one does not have anything for CSS. This one uses Redux and this one has no flux implementation…
Will these boilerplates be maintained? I have worked on two projects this year built from boilerplates and as of a couple of weeks ago, both had not been upgraded to Babel 6 and were silent on the issues tab (a response saying pull requests welcome would be fine).
2016⌗
To see something that streamlines the initial setup gaining enough mass that other developers are likely aware of it. This could be a boilerplate project, a command line tool like ember CLI, or a pre-configured webpack like hjs-webpack.
Universal Rendering⌗
The tagline for universal rendering I see is:
the same code running on the client and the server
Which is true, but with the experience of building apps doing universal rendering my more accurate tagline is:
most of the same code running on the client and the server
Why? The first tagline I feel gives the impression that doing universal rendering involves five minutes work flicking some switch for it to magically work.
The truth is universal rendering requires a lot more work than a purely client-rendered or purely server-rendered React app does:
- Writing JavaScript that the Node.js you are using does not understand? Then you need to create a transpiled server-side bundle as well
- Using any non-JavaScript stuff such as CSS and images in the components? Then you will need this handled/excluded correctly for the server-side bundle
- Ajax requests?
ReactDOMServer.renderToString
is a synchronous method so these will not fire off like they do for a client-side app - Forms need server-side fallbacks
- Tests that check both client-side version and server-side version? Because it is possible to break one while you are working and not realise it…
Many of the examples and tutorials on universal rendering only demonstrate one part: here is routing on its own, here is a form element on its own, here is the express server on its own.
It is only when you try putting everything together for the first time that you learn of all the extra work required.
(And universal apps are awesome when working).
2016⌗
More examples of universal rendering that incorporate multiple problems.
Testing⌗
My approach at the start of the year was mocha, jsdom, and react-test-tree. The advantages of this combination were I found the API nice and could write tests quickly. The disadvantage was that tests were slow to run.
Later in the year I switched to mocha and shallow rendering using the official test utilities. The advantage of this is the tests are quick to run. The disadvantages are I find the API and output returned not as friendly and subsequently writing tests takes longer.
Shallow-rendering returns a React element/JavaScript object:
{ '$$typeof': Symbol(react.element),
type: 'div',
key: null,
ref: null,
props:
{ className: 'globalCenter',
children:
{ '$$typeof': Symbol(react.element),
type: 'ul',
key: null,
ref: null,
props: [Object],
_owner: null,
_store: {} } },
_owner: null,
_store: {} }
Not as nice to work with compared to a HTML output and if you have nested parts of the html structure to check you need to drill down the props.children
part. I have used a couple of wrappers available for shallow rendering but they do not go far enough for me in making it easier to use.
Side note: I never tried switching from mocha to jest as every person I have spoken to at a meet-up who has used jest said they have since dropped it.
2016⌗
I think my issues are already solved with enzyme and expect-jsx. Will be trying enzyme on my next React project.
2015⌗
I have enjoyed using React and React + Redux is a nice combination. Making universal rendering possible is a huge feature despite the extra work required.
Another part of React I have liked is if it is required to do something irregular their is probably a github issue somewhere discussing it. Some libraries/frameworks become really difficult if you need to code ‘outside of the lines’.
Compared with AngularJS, I feel for the most part I largely know what I am doing with React and have been able to come on board to projects and start creating pull requests from day one. My experience with Angular1 was their were many things such as controllers, services, factories, and directives but not a lot of direction and I often wondered if I was building things that would come to be a bad approach later. It was only until after I had moved on that I started to see some decent guidelines on the correct approaches to use.
So React is great and I hope the tooling ecosystem around it becomes more sane.