Don’t mind me — just leaving some breadcrumbs behind for publishing and maintaining a React component on npm. Alan B Smith and I are working on react-zest, the first “serious” attempt at an open-source tool for either of us. This post is therefore a guide to developing open-source software from a beginner’s perspective. We’ve yet to learn many of the nuances, but we’re relatable and qualified to instruct you, the beginner, just a few steps behind.
A quick note on semantics
There’s commonly confusion about the terms
package to describe the thing you’re publishing. While these are technically different things, the difference is largely inconsequential. A
module is a unit of code that can expose (“export”) functionality. A
package is what houses one or more of these modules and contains a
package.json file. The term
library is more subjective, and depending on the definition you use, can be synonymous with either module or package. I tend to use
package interchangeably — sorry if that grinds your gears. Look to Google if you want more clarification (or confusion).
Right, then. How does one become an open-source author?
[ 0. Get real. ]
Don’t psych yourself out by trying to get it all perfect the first time around. The most likely scenario is that close to zero people will notice that you’ve published something, and even fewer will try it out or scrutinize your code. Phew, isn’t that a weight off your shoulders? When you’re comfortable and ready to share your code with the world, you might find that it’s actually quite difficult to recruit some users and collect feedback.
[ 1. Come up with the idea. ]
Yes, this is the hard part. In our case, Alan and I had been happily experimenting with some CSS animations for a client’s React project at Cognizant Quick Left. Having shared the goal to learn the dark art of open-source tool authorship, we ran with the idea of an animation library.
[ 2. Research existing similar ideas. ]
Validate that there is a reason for your package’s existence. Are there any libraries out there doing exactly what you had in mind? Are there existing packages that you think could be improved to meet your needs? What angle makes your idea unique? What can you learn from what’s already out there? There’s a massive (free) education to gain from examining how others have done it before you. If you’re just here to learn the mechanics, you might pick out an existing popular package to try and imitate simply.
There are a good handful of React animation libraries already out there — some that provide powerful low level control, some wrappers for other existing libraries, and everything in between — so we took some time to settle into our own little niche: a dead-simple suite of micro-animations.
[ 3. Design the public API. ]
This is just a first pass at how you want a user to interact with your library. For react-zest, we knew we wanted a simple wrapper component which could accept a number of customization props: animation name, animation trigger, and so on.
[ 4. Publish the package. ]
I strongly suggest publishing a practice, nonsense package before trying to publish your desired library. Getting the mechanics down might take a couple tries.
1. Name it.
The other “hard part” — choose a name. Search npm to make sure its not already taken. When you’ve found the one, create a directory with that name and
cd into it.
The react-zest name comes from the nature of micro-animations — they’re small additions to a web app that make the user experience just a little more fun or unexpected. Micro-animations add a little zest.
2. Get set up with git.
Initialize a new git repository with
git init. Create a new repo on GitHub with your chosen name, then add the new origin:
git remote add origin <github-repo-url>.
3. Add your user credentials to npm.
npm needs to know who is publishing the thing. Once you’ve got an account on npm, use adduser from the command line to authorize yourself. You can choose to set default author values in your
.npmrc file with the
npm set commands listed below.
npm set init.author.name "Your Name"
npm set init.author.email "email@example.com"
npm set init.author.url "http://yourblog.com"
4. Initialize the npm package.
npm init to begin the process of populating a
package.json file. Unlike a consumer app, the values in this file are actually consequential now. Don’t panic though, you can go back and edit anything before the first publish. Most noteworthy is the value of
"main". When a user downloads your package, it’ll execute whatever is in that file path. If you compile your library to a
build directory, the value of
"main" might be
5. Install dependencies.
Just like a consumer app, anything that your library will depend on in production needs to be saved in the package.json. If you’ll be using lodash, for example, it needs to be saved to
npm install --save lodash). When a user downloads your package, all dependencies will be installed as well.
6. Add tooling.
Hopefully you’re concerned about how large of a package you’re having your users download. Good news — all the tools you enjoy in consumer apps are still fair game, for two reasons: 1)
.npmignore and 2) devDependencies.
You can choose to use the works — webpack, babel, eslint, etc. — when developing your library. When it comes time to publish the library, babel or webpack can compile the bits you’d like a user to download, then omit the rest by adding files or directories to the
.npmignore file. So long as those tools are listed in your package’s devDependencies, your user will not have to install them. Light footprint == happy user.
7. Write the proof of concept.
Typically the module files will live in a
lib directory. Based off our React component example, the file structure might look like this:
Example.js in this case is just a standard React component and
index.js exports that component. That
index.js file is more of a style convention than a necessity.
8. Test it locally.
This workflow is particularly important. What you don’t want to do is publish a new version of your library every time you want to try out some new changes. Instead,
npm link is your friend.
When I finish a new feature in react-zest and I’m ready to give it a spin, I’ll run
npm link. This will create a globally installed symlink to my local react-zest directory. Now in a separate dummy app, I can run
npm link react-zest to create another symlink referencing my local react-zest directory. The result is that the latest react-zest code appears in my node_modules, without having to publish and download them again. Once I’m sure of the changes, I’m just about ready to publish.
9. Select the version number.
The first time around, you’ll choose what version number you’d like to start at. The first version number is pretty trivial and largely a matter of personal preference. The most common starting points are
1.0.0. If unfamiliar, you will want to acquaint yourself with semantic versioning. More to come on that later, as subsequent version number updates should be made with much more thoughtfulness. Alan and I chose to publish the first release of react-zest at
0.0.1, to indicate that its ready for some user feedback, but far from a useful, production-ready tool.
When you’re satisfied with the package, run
npm publish from the project root directory. This command will attempt to publish your package to the name listed in your
package.json, making it available to the public for download. Go ahead, search npmjs.com for your package name and do a little celebration dance.
11. Tag it.
Use git tags to demarcate version releases. As you might imagine, having versions synced up on GitHub and npm is awfully helpful when it comes to debugging specific version numbers. After you publish to npm, run
git tag <version-number-you-just-published>. In our case,
git tag 0.0.1. Then push the tag to GitHub with
git push --tags.
12. [Optional] Add another owner.
Working with a friend? Give them some credit by adding an additional owner to your package:
npm owner add <npm-username>. When in the root directory of the package, this will get the job done. For more fine-tuned permissions, see the documentation.
[ 5. Update the package. ]
What, you didn’t write a perfect piece of software the first time around? Updating a package is pretty straightforward.
1. Commit changes.
Make whatever feature addition, optimizations or bug fixes you have in mind for the next release.
2. Increment the version number.
This is important — focus! Based on the changes you’ve made, you can choose to increment the version number by a major, minor or patch level. Per the semantic versioning docs, breaking changes to the API calls for a major version bump. Feature additions (that are backwards compatible) are candidates for minor version increments, and bug fixes and the like are good patch updates. Deviating from this practice may cause you and your users pain! The primary goal here is not to surprise users with breaking changes when they weren’t expecting them.
A note about when to reach version
1.0.0 (also per the docs): if you’re using your package in production, it ought to be at
1.0.0. Version zero development is indicative of rapid development in the “early days,” and communicates that the API is unstable and liable to change out from under you on any given day. However, these are just guidelines. Several well-established version zero libraries are widely used in production environments. React, for example, was widely used all the way up to version
0.14.X. The maintainers acknowledged this deviation from traditional semantic versioning by releasing the next version at
After making your changes and bumping the version number. Run
npm publish again from the root directory of the package.
4. Tag it.
Same dance as before:
git tag <new-version-number>, then push the tag to GitHub with
git push --tags. Note that you can use the GitHub GUI to add detailed release notes.
[ 6. Get a logo. ]
If you want to be taken seriously, you’re going to need stickers. And to get stickers you’re going to need a logo.
That was a joke. Please spend your time writing good software instead. Alan made up this little logo, because he enjoys graphic design in his spare time.
[ Aw yeah. ]
Go forth, you open-source prodigy. Get publishing and enjoy the all stars along the way. There’s always more to learn — especially when other interested contributors enter the picture — like how to conduct pull request code reviews, write good documentation, and communicate your vision for the future of the project. Let me know — what are you working on?