A Tale of Two Libraries
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.
At some point after I reached that “maybe-I-don’t-totally-suck-at-this” phase, I started helping a friend with a project that needed a front-end app. It seemed like it would be a good fit for React, so I though this would be a nice opportunity to start with a fresh project and see the best practices of people out in the JavaScript community.
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.
It came time to do some styling, so I asked Lauren (my wife, she’s good at that – she also taught me JavaScript in the first place) if she could help us out. I got node and everything installed on her laptop, and we realized… where do we put stylesheets? Where do we put assets? How do we require librarires? We had to add a webpack loader, where did the config go?
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.
My second point is that even if you are an outsider to a community, a little scepticism can be healthy. I try to approach languages and frameworks openly, with the belief that their practices evolved naturally and their patterns must work for them or else they wouldn’t have made it that far. This is especially true when it comes to something like JavaScript, where there is a rapidly evolving, complex ecosystem full of brilliant people. Who am I to tell them how to do things? I am not an experienced front-end professional like these people! Yeah, well, those are nice ideas and all but they betray the fact that I am not new to code, organizing projects, or the patterns and practices that lead to maintainable, reasonable production-ready code. You, reader (JK nobody reads this), might be in a similar situation, and to you I say: trust yourself. Don’t immediately shit on other ways of doing things but if something strikes you as weird – too engineered, too sprawling, oddly-named, whatever – you’re probably right. You don’t have to be a fucking JavaScript expert to see that.
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.