Building and maintaining a React library can be a large task, even for small libraries.
You start off thinking that you just have to figure out how to properly build and package your code. And then quickly you realize there’s a ton of configuration options and combinations of tools you can use. You have to make sure you have your package.json, tsconfig, linting story, docs, and more in line. If you are supporting Next.js, you may have to add "use client" banners everywhere, and make sure your build system isn't stripping them away... because they definitely will be removed by default.
Once you have all that figured out, you are left with one final question… does this actually work?
And I don't just mean adding unit tests. I mean, if a user installs it in their application, does it do what you expect?
For that, I wanted to highlight a tool that brings so much sanity and joy to an otherwise frustrating process: yalc
Before yalc: npm link
Let’s say we just finished up a React library. We're ready to set up a GitHub action that runs
npm publish and let the world use what we’ve built. Before we do that, we want to try it out for ourselves in a real application.
One option is we could just publish and test it. We could mark it as an alpha release so potential users are warned to not use it.. but this feels a little strange. Our library and application are both local, after all.
We google around and find npm link, which seems like the answer we are looking for. The description is so promising:
This is handy for installing your own stuff, so that you can work on it and test iteratively without having to continually rebuild.
However, after linking our React library to our application, we get an error:
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See for tips about how to debug and fix this problem.
It links us to the legacy React docs which gives us a lot of advice that doesn’t seem to apply to us. We aren’t using hooks in functions or have mismatched versions of react and react-dom?
Making a long story short, what is actually happening is that there are two different copies of the
react package being used. When we run npm link, we don’t just need to link our project, we also need to link react and react-dom to make sure there’s only one copy.
This works, for now, but our workflow got more complicated from when we thought we could just run
npm link and be done with it. It gets worse if you manage more than one React library as you might need to constantly need to unlink and relink different Reacts.
Yalc to the rescue
This is exactly the problem that yalc solves. In their own words, yalc is a “Better workflow than npm | yarn link for package authors.”
With yalc, you can run:
in your React library, and then run
yalc add my-package-name
in our application, and that’s it.
yalc publish publishes the package locally, so you aren’t exposing it to everyone.
There’s no duplicate versions of React or cryptic invalid hook errors. It functions the same way that it would if we were publishing to npm. And that’s really it, it operates exactly as you would expect it to.
There are a few more advanced options, like you can run:
yalc publish --push
which will both publish locally and run
yalc update in all the locations where your package was added.
Building a React library is hard enough, especially as the ecosystem changes with React Server Components and other changes library maintainers have to worry about. yalc takes an otherwise frustrating part of this process and makes it actually just work.