Credit: Getty
I've built free web-apps fulfilling various practical purposes (mostly silly) for quite some time, but it wasn't until fairly recently (~1 yr) that I started getting into open-source software (OSS). It has opened my mind to a whole new world and has had an enormous impact on my general understanding of JavaScript and its ecosystem. This extension of knowledge was partly thanks to contributing to open-source projects but even more so by simply reading a lot more source code written by other developers. The realization that all source code is written by mere mortals, and that it doesnโt bite, caused the threshold for deep diving into libraries whenever issues arose to be significantly lowered.
Learnings
My OSS journey hasnโt been without bumps in the road. But where thereโs bumps, thereโs learnings.
Git & npm: The Confusing Parts
npm tags
Git and npm has a lot of overlapping terminology which can be confusing at first. When starting out with developing my own projects I had a lot of assumptions as to how the two platforms interacted. For example, a misconception I had early on was that npm would interpret my libraries' versions and make contextual decisions, such as "marking" a release published as 0.0.1-alpha.0
as an alpha-release rather than a latest-release. However, even though 0.0.1-alpha.0
is completely valid semver, npm requires that one explicitly tag releases: npm publish --tag alpha
.
A npm tag can be pretty much anything except for something resembling semver. For example,npm publish --tag ihavenoideawhatimdoing
is completely valid:
git tags
We just learned what a tag is in npm's world. What about Git?
A tag in Git is essentially a snapshot of a repository at a particular time in its history. Dealing with Git tags is fairly straightforward. The weirdest part is that the tag's name can be literally anything and doesn't have to conform to semver. Developers commonly use tags to help mark releases and thus, for sanity's sake, use their library's version as a Git tag (prefixed by v
of course ๐คท๐ผโโ๏ธ):
# Create tag
git tag v0.0.1
# Push to repo (will turn up as a commit)
git push --tags
TypeScript
Building your library in TypeScript?
Expose your type declarations
There's a ton of options for compiling TypeScript projects. However, there's one in particular that'll make whoever depends on your library super happy ๐ผ:
{
"compilerOptions": {
"declaration": true
}
}
This'll generate declaration files (file.d.ts
) next to each JavaScript file outputted from the compilation that'll be exposed to your users when they import your library.
Fighting your IDE ๐จ๐ผโ๐ป๐ฅ
The relevance of this particular tip may vary depending on your IDE.
There's a wide variety of IDE's out there, from those that give absolutely zero support whatsoever to those that borderline autocompletes your thoughts. My current IDE of choice, VS Code, is somewhere in the middle of this range. It is equipped with a bunch of debugging tools and a solid selection of extensions, improving developer experience via customizability. In a perfect world a developer wouldn't have to run e.g. ESLint's CLI but would solely rely on an extension that'd guarantee the same experience.
When developing TypeScript your IDE relies on your tsconfig.json
to validate your code and highlight type errors. This behavior, as intended as it may be, causes some level of cumbersomeness when publishing your library to e.g. npm.
Why?
Well, hopefully, your project is blessed with at least one unit test. Ideally, tests shouldn't turn up in the distribution code, i.e. the dist, just as development dependencies shouldn't turn up in production. However, using exclude
in your tsconfig makes VS Code a sad ๐ผ and you'll see the errors such as:
Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try
npm i @types/jest
ornpm i @types/mocha
.
I haven't found any better workaround than to include all TypeScript files in my tsconfig.json
and create a separate tsconfig.publish.json
that'll be used when publishing to npm. This setup makes VS code happier...
...but forces developers to remember yet another detail before publishing: compile the dist using yarn tsc --project tsconfig.publish.json
instead of simply yarn tsc
.
Pipeline - automate automate automate
A colleague of mine who's an OSS wizard once recommended me to automate as much as I possibly could for my projects. Not being a huge fan of pipelines and such, I kindly nodded and postponed the advice as long as possible.
However, my patience finally got the best of me. I learned the hard way that a bunch of manual steps easily led to mistakes and ultimately frustration. Lucky for me, GitHub Actions had just been released and it matched my level of interest in DevOps. With it, I could fairly painlessly create workflows that would automate everything I needed in order to publish libraries.
What kind of steps does this entail? Well, here's roughly the flow of my pipeline:
- Linting: Running e.g. ESLint is a great way to discover problems without having to run any code.
- Tests: Just like the responsible developers that we are, there's plenty of tests validating that our code can do stuff, even better if it does what it's supposed to. Extra points for integration tests โจ
Since we only wish to publish to npm on version bumps, the following steps only execute on git refs starting with refs/tags/
-
Publish library: Install dependencies, build the dist and publish to npm. This step also attaches necessary npm tags, for example
v0.0.1-alpha.0
results innpm publish --tag alpha
. - Build and deploy website: Creating a website for your library's documentation is pretty sweet once the README starts occupying a few viewports. I recommend Docusaurus since it's easy to use and deploy.
Conclusion
This article was intended to outline some of the challenges I've encountered during my adventures on GitHub, I hope it inspires more than it frightens ๐๐ผ
If there's interest I'd be happy to share more on this topic!
Top comments (0)