惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
C
CERT Recently Published Vulnerability Notes
C
Cisco Blogs
Cloudbric
Cloudbric
The Last Watchdog
The Last Watchdog
L
LINUX DO - 热门话题
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Archives - TechRepublic
Security Archives - TechRepublic
TaoSecurity Blog
TaoSecurity Blog
V2EX - 技术
V2EX - 技术
H
Heimdal Security Blog
S
Security Affairs
L
Lohrmann on Cybersecurity
Hacker News - Newest:
Hacker News - Newest: "LLM"
Simon Willison's Weblog
Simon Willison's Weblog
WordPress大学
WordPress大学
小众软件
小众软件
Security Latest
Security Latest
AWS News Blog
AWS News Blog
Apple Machine Learning Research
Apple Machine Learning Research
GbyAI
GbyAI
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
F
Full Disclosure
S
Schneier on Security
L
LangChain Blog
MyScale Blog
MyScale Blog
Know Your Adversary
Know Your Adversary
P
Privacy International News Feed
Google Online Security Blog
Google Online Security Blog
Scott Helme
Scott Helme
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
A
Arctic Wolf
Martin Fowler
Martin Fowler
B
Blog RSS Feed
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
The Register - Security
The Register - Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
Latest news
Latest news
F
Fortinet All Blogs
G
GRAHAM CLULEY
T
The Exploit Database - CXSecurity.com
Hacker News: Ask HN
Hacker News: Ask HN

Kent C. Dodds Blog

Implementing Hybrid Semantic + Lexical Search Simplifying Containers with Cloudflare Sandboxes Migrating to Workspaces and Nx Offloading FFmpeg with Cloudflare Building Semantic Search on my Content Helping YOU ask ME questions with AI How I used Cursor to Migrate Frameworks The Dow's Start on the Covenant Path 2025 in Review The next chapter: EpicAI.pro AI is taking your job How I increased my visibility Launching Epic Web 2023 in Review Stop Being a Junior RSC with Dan Abramov and Joe Savona Live Stream Fixing a Memory Leak in a Production Node.js App 2022 in Review My Car Accident I Migrated from a Postgres Cluster to Distributed SQLite with LiteFS I'm building EpicWeb.dev A review of my time at Remix Remix: The Yang to React's Yin How I help you build better websites Why I Love Remix The State Initializer Pattern How to React ⚛️ Get a catch block error message with TypeScript Building an awesome image loading experience How Remix makes CSS clashes predictable Introducing the new kentcdodds.com How I built a modern website in 2021 How to use React Context effectively Static vs Unit vs Integration vs E2E Testing for Frontend Apps The Testing Trophy and Testing Classifications Array reduce vs chaining vs for loop Don't Solve Problems, Eliminate Them Super Simple Start to Remix Super Simple Start to ESModules in Node.js JavaScript Pass By Value Function Parameters How to write a Constrained Identity Function (CIF) in TypeScript How to optimize your context value How to write a React Component in TypeScript TypeScript Function Syntaxes Listify a JavaScript Array Build vs Buy: Component Libraries edition Using fetch with TypeScript Wrapping React.useState with TypeScript Define function overload types with TypeScript 2020 in Review Business and Engineering alignment Hi, thanks for reaching out to me 👋 useEffect vs useLayoutEffect Super simple start to Firebase functions Super simple start to Netlify functions Super Simple Start to css variables Testing Implementation Details How getting into Open Source has been awesome for me useState lazy initialization and function updates Use ternaries rather than && in JSX Application State Management with React Use react-error-boundary to handle errors in React JavaScript to Know for React How I structure Express apps What open source project should I contribute to? When I follow TDD AHA Programming 💡 How I Record Educational Videos Should I write a test or fix a bug? Stop mocking fetch Intentional Career Building Improve test error messages of your abstractions Tracing user interactions with React Eliminate an entire category of bugs with a few simple tools Common mistakes with React Testing Library Super Simple Start to React Stop using client-side route redirects The State Reducer Pattern with React Hooks Function forms Replace axios with a simple custom fetch wrapper How to test custom React hooks React Production Performance Monitoring Should I useState or useReducer? Stop using isLoading booleans Make Your Test Fail Make your own DevTools An Argument for Automation Fix the "not wrapped in act(...)" warning Super Simple Start to ESModules in the Browser Implementing a simple state machine library in JavaScript 2010s Decade in Review Why users care about how you write code Why I avoid nesting closures Don't call a React function component Why your team needs TestingJavaScript.com Inversion of Control Understanding React's key prop How to Enable React Concurrent Mode How to add testing to an existing project Profile a React App for Performance
Favor Progress Over Pride in Open Source
2020-08-24 · via Kent C. Dodds Blog

I have published a lot of open source packages. Most of them are not that popular, but I want to tell you a story about one that got really popular really quickly and then experienced a rapid decline in popularity because I deprecated it in favor of an alternative library.

download graph for glamorous

When CSS-in-JS was growing in popularity, I was inspired by existing solutions, but I thought I could do some things better than other solutions out there (the biggest player in the space was styled-components), so I created glamorous and published it to the world.

Whenever I release a new open source package and other people start using it, it strokes my ego in a big way. It's extremely validating. In the case of glamorous, it picked up steam really quickly. It even surpassed downloads of styled-components (though download stats aren't a very good metric of popularity, they're really the only metric we have).

In any case, it was my most visible and popular open source project by far. But when an alternative solution came around that was objectively better and we had a reasonable migration path (that's important), I deprecated it without any hesitation. The alternative was emotion. Here's what I said about this when I asked the community what they thought:

Here's my reasoning:

  1. Emotion can do everything glamorous can do
  2. Emotion can do more than glamorous can do
  3. Emotion is faster than glamorous
  4. Emotion is smaller than glamorous
  5. It's good for the community to consolidate and rally around using and improving a single solution

This is only one of a variety of examples of projects I've either deprecated or handed off. In either case, the core is the same: I solved a problem, and then handed the torch to someone else.

But my pride!?

A common theme I see in open source is people being upset or frustrated when someone else comes up with the solution to a problem first. Whether it be as big as a library or as small as a pull request. I can understand this feeling, but let me explain how I think about it and hopefully this will help you cope with these situations and see them for the heavenly blessing they really are 👼

Let's put it in a generic storyline (with fictional characters):

  1. Brad identifies a problem
  2. Brad solves the problem and is willing to maintain it long-term
  3. Mary identifies the same problem
  4. Mary solves the problem better than Brad with a reasonable migration path and is also willing to maintain it long-term

What should Brad do in this situation? Every specific situation will be a bit different, but here are a few options I think would be reasonable:

  1. Mary and Brad collaborate and bring Mary's solution into Brad's package and they're now co-maintainers of the original package, only with Mary's improved solution under the hood. Publish a major version and a migration guide.
  2. Brad deprecates his solution and directs people to a migration guide to move to Mary's solution instead.

Let me tell you what would not be a reasonable thing to do:

  • Brad gets upset at Mary and works hard to make his solution better until it's as good as Mary's

This means we now have two solutions for the same problem. It fragments the community and gives developers yet another choice in the myriad of choices people need to make just so they can get to building the apps they want to make. It also fragments the efforts of the community. People are often putting in the same work to solve the same problem in two places.

To be clear, I can appreciate different takes at solving the same problem with different trade-offs. But only when those trade-offs are different enough to justify the double-work and forcing everyone in the community to take the time deciding between the two. Unfortunately, we have far too many packages that aren't nearly differentiated enough to justify continued use and work on them.

Also, to reiterate, I think it's important that we support people who have invested in tools and technologies. So if a migration is very difficult, then that could justify continued work on the package as well. Also, if a migration is difficult, then it's also likely the trade-offs made are significant enough for the decision anyway. Unfortunately again, we have far too many packages that aren't all that difficult to migrate to a better solution.

Another thing to keep in mind is that migration is only really needed in the event of a relevant security vulnerability or desire for bug fixes and features. So deprecating a inferior solution in favor of a better one will only impact people who would be interested in migrating for the improved solution anyway. Things don't suddenly stop working when they're deprecated.

The sunk costs of pride in OSS

So when you've got two or more packages that don't make sufficiently different trade-offs and aren't difficult to migrate from, you're making the community incur a cost. This is a real issue (anyone building apps has experienced the frustration of deciding between similar solutions to a problem). The solution is to look at the situation objectively and ignore the sunk cost of all the effort contributors have put into the inferior solution. Continuing to work on yours (and inviting the work of others) when an objectively superior solution could reasonably be used instead is (frankly) selfish and prideful.

Deprecation is a gift

The people who created emotion were actually active contributors to glamorous. When I learned that they were working on a completely new solution, I was a little bummed that we couldn't just make glamorous better. But on the other side of things, I was thrilled. It meant that someone else was going to work on solving the problem I had experienced and I could move on to something else. I knew the problem was in good hands. There are too many problems to be solved to throw a fit over something like this. Move on to the next problem!

Nuance

I'm not sure how else to organize some of these thoughts, but I need to include them, otherwise people will think I'm suggesting that Angular should be deprecated in favor of React (it should not).

What if we don't agree one is superior?

You each likely have a list of reasons why your solution is superior. Put that list in your docs in a prominent place to help people make the decision you're forcing them to make.

If you can't come up with a list, then are you sure it's not just your prideful knee-jerk reaction? No shame, spend a few minutes comforting yourself a bit, and move on.

What if it's hard to migrate to the better solution?

This question is only mentioned because I'm sure people will miss the fact that I mention this several times in the post above. Is that you? If it's hard to migrate, then keep working on it. But I'd suggest adding a note to the docs that a superior solution exists so new folks start with the better solution. And you might also work on finding ways to make a migration less painful.

What if we can't collaborate?

As long as the solution solves your problem, then who cares? If they're working on the solution, then that leaves you to be free to work on the other stuff you want to work on!

What if I just want to work on it?

Then heck, work on it, but please mention in the docs that a better and recommended solution exists if one does and save people the time.

What if this is a product I sell?

Well, that's pretty different. In that case we're talking competition and you actually do want to win people over to your solution so you can make money. If someone else legitimately has an objectively better solution, you'd better find a way to differentiate yourself fast or you'll be looking for a new problem to solve whether you want to or not 🙈

Conclusion

Just remember that having multiple solutions to the same problem has a cost on the community. Sometimes that cost is worth it, but so often it's not. When emotion was released, I saw that the implementation was objectively better, it would be well maintained, and thanks to my friend Tejas Kumar, we had an automated way to migrate people's codebases.

It would have been selfish of me to ask people to continue investing their time into glamorous. Deprecating it was one of the best decisions I made. I freed everyone up to move on to the next problem, and I think the world is a little bit of a better place because that.

Do you have an open source library? Are there better alternatives? Save yourself and everyone else some time by adding a note and a link in your docs (and possibly even deprecating the package in the registry). It'll make things easier for everyone. Good luck!