When I noticed the upcoming anniversary in my calendar, I could only think of one question to reflect on: why did Lineman fail and what can we learn from it today?
(You might be reading this thinking “all that is still true,” and you wouldn’t be wrong, but it was even more true a decade ago, if you’ll believe it!)
Lineman hasn’t been actively maintained for a long time, so don’t go adopting it now. We still use it to build testdouble.com, though, and I’m sort of amazed and delighted it still works!
We created Lineman to solve all of these problems.
(Also, Dave Mosher drew this logo. And once your project has a logo, you’re obligated to follow through with a bespoke marketing web site—that was just an ironclad rule of open source at the time.)
A few highlights of Lineman’s main features (and an archive of that aforementioned doc site):
lineman newgenerated a ready-to-deploy project that, importantly, didn’t duplicate a bunch of code or configuration. Defaults were stored in Lineman itself, so users only had to specify how their app deviated from the golden path. This compared favorably to Yeoman scaffolds or (much later) Create React App, which littered your project with details that were out of date as soon as they were generated
- The testing story (
spec-ci) was a sheer delight by contemporary standards and probably still beats most frontend developers’ lived experience today. This was thanks in large part to Toby Ho’s Testem runner, which could run all your tests against multiple browsers simultaneously in a slick interactive CLI after every file change
- It’s commonplace now, but
lineman buildwas the first tool I’d ever seen designed to create performant and cacheable assets for production out-of-the-box. It was CDN-friendly from day one: concatenating, compressing, and fingerprinting production JS, CSS, and image assets without requiring users to configure anything or maintain a file manifest
- The plugin API could be used to add new JS/CSS/HTML languages and compilers with zero config for users beyond adding the plugin as a dependency. Because Lineman’s core functionality was implemented with plugins, third-party plugins could so dramatically change Lineman’s default behavior that a one-line change to
lineman rundevelopment server included my favorite feature—and the one I’ve seen least often elsewhere—the ability to mock out HTTP endpoints to facilitate rapid prototyping and define executable API specifications. This empowered frontend developers to stay productive when a backend API was unfinished, while still proxying requests to the routes that were available. And if that backend was too slow, stubbed routes could unlock much faster feedback than running each page load through the full stack
Later on, Jo Liss created the much more rigorous Broccoli asset pipeline and Stefan Penner used it to build the really-very-good Ember CLI. I toodled around on a framework-agnostic Broccoli-based build tool, but never managed to cross the finish line. Lineman was basically “finished” by 2015, in both senses of the word.
But, in the end, we all know what really happened: React ate the universe.
The worst timeline—the one I spent years warning people of—ultimately came to pass: myriad frontend teams would be saddled with hundreds of out-of-date dependencies, configuration files generated by a CLI command that doesn’t work anymore, and application code so hopelessly tangled with their build tooling that by 2018 Test Double was seeing a glut of “legacy rescue” React projects. I started hearing from VPs of Engineering who’d decided to pursue server-side rendered React but were seeing such anemic productivity they were now reversing course and upgrading their atrophying Rails monoliths (whose frontend strategy is also finally coming together a decade later).
Before drawing any lessons from Lineman’s failure, it’s worth asking “what drives the popularity of the most successful frontend tools in the first place?”
A few examples from blockbuster frontend open source projects:
- When React started spreading internally at Facebook, open sourcing it gave them a rare opportunity to win goodwill with the software community they needed to hire from (unforced licensing controversies aside)
- Google burnished its “open web” bona fides by hiring a team around AngularJS and a stack of related tools to deepen the moat surrounding its vision for the web as a platform
- Speaking of, Microsoft winked at AngularJS once, and suddenly half the booths at NGConf were populated by legacy .NET vendors selling paid component libraries
- Cypress provided a genuinely novel UI testing experience, but they also took on enough outside funding to lead them to blocking libraries that undercut their cloud service
- Insomnia, an open source API client that looks an awful lot like Postman (right down to its business model), apparently started requiring a registered account to function, despite the fact most of its users adopted it to avoid signing into Postman
Large or small, what each of these projects had in common was a powerful incentive to not only invest in the creation of open source tools but in marketing them, too. And in each case, the roundabout nature of that underlying incentive wasn’t exactly spelled out in the README.
Lineman did something people didn’t think they needed, and we lacked the marketing horsepower to convince them otherwise. Perhaps more importantly, Test Double’s business model doesn’t incentivize us to incur significant expense to maximize our open source projects’ adoption.
Lineman may have failed to take the world by storm, but it was hardly a waste of time: it supercharged Test Double’s ability to deliver great web apps and informed our team’s thinking about how to coach clients amid an increasingly dizzying landscape of frontend technologies. But Test Double pays the bills by serving clients who (rightly) care more about outcomes than implementation details, so scoring points on Reddit and Hacker News wouldn’t have really moved the needle for us. And while I empathize with anyone who had a Bad Time™ fighting half-baked frontend tooling this past decade, I’m not too salty that our little tool didn’t succeed. Hell, if Lineman had taken off, the open source maintenance burden would have been such a distraction that it probably would have hampered Test Double’s success in other areas.
Every developer has a handful of tires they kick before adding a dependency to a project. Check the download count. See how many GitHub stars it has. Verify the most recent release wasn’t too long ago. See how many contributors are actively committing to the project. Make sure there aren’t a thousand open issues with titles like, “postinstall script contains ransomware that stole my customer data.”
You know, the basics.
But one thing they don’t teach you at programmer school is how to evaluate open source tools in the context of the broader economy. What company is sponsoring it and why? How would that company stand to benefit if the tool they’re promoting dominated the industry?
Going forward, consider not just the popularity of a tool, but the incentives of whoever’s promoting it. When two tools both have GitHub READMEs, both
npm install the same way, and both purport to solve the same problems, we tend to compare them on equal footing. But, if one tool is backed by a growth-stage SaaS company and one is a humble community effort, it’s probably time we start factoring that into our decision criteria.
As a worst-case thinker, here are a few questions I think through before adopting a nontrivial dependency:
- How many dependencies does it have? If I install this thing, how many transitive dependencies am I saddling myself with?
- Can I isolate it from the rest of my code via an adapter object I own or must it “infect” the rest of my code, tests, or build configuration in a way that makes switching more difficult?
- If a project isn’t particularly active, is it because it’s dangerously unmaintained or is it simply a small, encapsulated “solved problem”?
- Do I know any likeminded developers who’ve used it in anger for more than a few months and, if so, what’s the worst thing they’ll say about it?
- If the company sponsoring it turns heel and embraces the dark side, would a community-maintained fork be feasible?
All of these questions basically redound to, “how screwed would I be if this thing goes south?” If I don’t like the answer to that question, I’ll go out of my way to explore alternatives or find a way to eliminate the need for the tool entirely—adopting it only as a last resort.
Leering skepticism comes naturally to me, but even if you’re wired differently, it’s probably safe to say the industry has earned our critical thinking before we adopt whatever tools they’re peddling.
As someone who’s created a lot of open source and who consorts with other open source maintainers, I dare say my experience has been much more positive than average. So here’s some free advice on why open source contribution has worked for me and why it doesn’t work for others.
How to have a good time:
- Create an open source thing in the course of your needing it yourself, don’t try dreaming up what others might need (and why would they? You don’t even need it!)
- Focus your efforts on helping those who express an interest in your thing, not on convincing the people who don’t
- Look for an employer that will benefit from you open sourcing things, but don’t try to get paid directly to make open source. Developer relations budgets are always first on the chopping block. Sponsorships significant enough to pay the bills are ephemeral and come with strings attached
- Don’t add configuration options when people ask you to. Every additional
ifstatement compounds the combinatorial complexity of cases to test, and the code paths you don’t use yourself will be the ones you find yourself fixing most often
- Don’t add dependencies that aren’t absolutely necessary. Every direct dependency for you is a transitive dependency for your users, and represents a point of failure that could strike at literally any time without your involvement. The median number of dependencies in libraries I’ve published in recent years? Zero
- As soon as you’re not having a good time, stop. You don’t owe anyone shit, much less your free labor
If this discussion has stimulated anything you’d like to sound off about, shoot me an email. If not, join me in pouring one out for Lineman, anyway.