Work has kept me busy this year, but the past few months were slightly more of a challenge than usual when I was thrust into the world of front-end development. All of our front-end engineers were gone, updates were needed, I like learning new things, so that was that. We have two React apps at work, one slighly older that uses Flux, another a bit newer using Redux. They were each configured by different people and demonstrated many different ways of doing things. After a few weeks of writing production code and quite a few frustrated IMs to friends, I reached a point where I was feeling good about my time with JS, React, and front-end development as a whole.
This is not a story about that, though.
I had it in my head that configuring Webpack, React, Redux, etc,… from scratch was a pain in the ass. Since the setup portion was the area that I felt least confident, I thought I would do some research and find the best React starter repo and use that as a template. After all, a popular project would probably reflect the current state of the art and include all kinds of helpful things that I and my former co-workers might not have known about!
I did some research. I wanted something that already had React 15 and the modern versions of React-Router and Redux. I wanted it to preferably already have a test framework setup. It had to use webpack, naturally, have SASS support, and hot reloading. These requirements didn’t seem too demanding but findind the right library proved a little tough. There’s a lot of old stuff out there, a lot of of libraries using old versions or missing pieces. Finally, I settled on an extremely active React starter project that had all the right versions, the right config, the right number of Github stars, the right number of contributors and people responding to issues. Sweet! I cloned, I copied into a new repo, I got to work.
Things were weird right away. The sprawl was insane. Unreal. Every conceivable tactic to split this project into extra files had been employed. Each route was split into pieces, some routes had dedicated components, others had dedicated containers, others… those are just routes, you have to find the rest of those pieces. The webpack config was split and split and split. Always quick to assume that I’m just a primitive Ruby engineer who doesn’t understand the ways of these sophisticated front-end professionals, I put my head down, refactored it a bit to make it more sensible to me, and pushed through.
It worked for a little while. Sure, every time I had to add a new route or component, I felt like I was jumping through flaming hoops that were also screaming at me and dancing around and covered in spikes, but… I just had to adapt to their modular approach! This was a “fractal” file organization, broken up by features. (Forget the fact that today’s unshared, feature-specific code and assets are tomorrow’s reusable time-saver and this reeked over pre-optimization.) I spent more and more time. I wrote some cool code. Things started coming together.
Somewhere along the line, I simplified the routes, components, and containers to look more like one of my apps at work. It felt less sophisticated but no matter how much I read, I couldn’t find any evidence that anyone else was actually using this library’s approach to file organization. Oh yeah, also, my huge production apps at work looked nothing like this and they were doing fine. Oh, and no repo that I had ever looked at was organized like this. I again considered that maybe there was something wrong with this library’s approach.
Those flaming hoops that we had to jump through to make things work? There were no hoops at this point, just fire. We had to find a way to just jump through the fire and make things work.
After a lot of stress, we got everything working. The app was styled, everything looked good!
Finally – finally! – things seemed pretty stable. I thought everything could be left alone for a little while.
But then I read about this cool new library: webpack-dashboard. It made my webpack config look all… pretty, ‘n stuff! I wanted to use it. I started following the documentation aaaaand…
Everything broke. Everything fucking broke. I could not figure out where to even start making the simple changes required to make this thing work.
That was the end! Fuck this shit! I decided to find another library to use as a baseline for the project. I’d rip my code out, configure the stuff I didn’t want to configure before, and know that I had something predictable.
A few weeks after I started the new project, create-react-app was released. It was super barebones – no Redux, no Router, no tests, no SASS – but fuck it! I’d figure out the rest!
I cloned it, I ejected (cause I’m a control freak who likes to see more of his dependencies), and guess what jumped out at me immediately?
It was so. fucking. simple. There were so few files. It was so predictable. There were a few clearly configurable options, but it was all totally declarative, easy to expand, easy to reason about. I quickly wired up everything I needed, ported over my code, and had it working. Since then, there have probably been a dozen little tweaks I had to make to my webpack or test config and it never fucking surprises me or breaks. I keep an eye on the project’s repo to see what changes they’re making and if I see something I like, I follow their lead.
WHAT’S MY FUCKING POINT, THEN?
I’ve got a few.
My first point is that complicated code is not necessarily healthy code. Libraries that aim to be all things to all people run the risk of becoming amalgamations of many organizations’ infrastructures, not examples of how any one organization would ever handle their infrastructure! The first React starter library I used was more of a tech demo (“LOOK AT ALL THE CRAZY SHIT YOU CAN DO WITH REACT!”) than a reasonable approach to project organization.
Finally, remember that at the end of the day, doing things “right” by the standards of a community (of fucking strangers, who gives a shit?) should be secondary to feel productive and shipping. Don’t feel obligated to change tech or put up with patterns that just do not seem to be sticking if it’s getting in the way of your work. I should have punted on the first library right away.
And that’s that. I’ve been happy as a clam since then, coding and shipping. My project is getting pretty intense and I’m eyeing TypeScript as a way to make things more reliable. I branched and started the conversion but noticed a lot of weirdness around the different approaches to obtaining type defs, so once I spend some time configuring my project for global typings and… WAIT A MINUTE. NOT THIS AGAIN. I’M WAITING FOR 2.0.