Picture this: You're using the many-small-repositories approach to work faster as a team.
You've got an admin repo, a backend repo, a mobile repo, a repo for the corp site, another for the main web app, a few experiments that died in A/B test, and let's be honest there's multiple backend repos. One per service. Web app likes to grow into multiple repos, too. One per user concern.
You get more done faster and each codebase makes sense on its own. You can even deploy separately 🤘
And then your plan falls apart 👉 shared code.
The first candidate is your design system. After that come utility functions. Then user management and shared API queries.
Best solution I've found for those are internal libraries. Libraries built for you and your team. Not meant to be shared.
If they prove out, you can open-source later. Like Facebook did with React. But that's a lot of work, trust me.
How to create a JavaScript library or package
Don't overthink this one. A JavaScript library is a bundle of code with a package.json
file and a name.
Easiest way to get started is to:
1 create a new directory
- run
npm init
- follow the prompts
You'll get a basic package.json
file:
{
"name": "example-library",
"version": "1.0.0",
"description": "This is an example to show a basic package.json",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Swizec",
"license": "MIT"
}
I recommend keeping your code in src/
. Export your public interface from src/index.js
.
Internal libraries like to skip that step and it makes them hell to use. You want to hide implementation details.
// this leads to tears
import { FooUI } from "example-library/src/thingamabob/foo/UI";
// aim for this
import { FooUI } from "example-library";
// or this if there's many areas
import { FooUI } from "example-library/foo";
Another good idea is to add a compile step. Get support for TypeScript, any Babel plugins you're used to, etc.
I like to use microbundle for libraries. Quick to set up, works great, keeps code small.
How to maintain a private library
You want to treat private libraries with the respect you'd give a public library.
Follow semver as best you can – major version for breaking changes, minor for new features, patch for bugfixes. You'll use different versions of the library in different projects. Upgrade as needed. Semver helps you keep track.
You don't want a situation where every project is forced to upgrade when any project upgrades.
Ask me how I know 😅
- Use
npm version major/minor/patch
to release versions. It updates package.json and adds a new tag. - Use
git tag v1.1.0 v1.1.0\^\{\} -f -m "changelog"
to add a message to your tag git push origin --tags
to update your code
Using tags for versions and the changelog creates a nice browing experience on GitHub. Tags show up as releases and you can see what each version means.
Here's useAuth for example:
Treat libraries as real projects. Have an owner. "I owned X library used by 5 products at \\$Company" Looks great on your resumé [name|] 😉
Git branch – the poor man's private package
Quickest way to distribute private packages is through GitHub. You're all set up already.
Your company likely uses private GitHub repositories. That means your build/CI/deploy pipeline has access. 🤘
Here's what you do:
npm install company/repo
or
yarn add company/repo
You get a package.json entry like this: github:company/repo
Yep! NPM and Yarn have built-in support for installing packages off GitHub repositories. Master branch by default, specify a version with a hash like this: github:company/repo#v1.0.0
No support for automatic semver upgrades. Pinned versions only.
Private NPM packages
A step up from github branches are private NPM packages. You'll need a paid account to enable this option.
NPM is the default package registry which makes this option easy to configure. No configuration for personal use.
You'll need to scope your package in package.json
:
{
"name": "@swizec/private-package"
}
Now you can run npm publish
to publish as a private package. npm install @swizec/private-package
installs it.
For team and collaborator access, you'll need to create a new token in settings. Anyone who needs access (person, server, etc) will use an NPM_TOKEN=...
environment var.
That's all you need ✌️
Private NPM packages with Yarn
I ran into issues using private NPM packages with Yarn. Errors out with packages it can't find.
You can fix that with a .yarnrc
file in project root:
.yarnrc
"@swizec:registry" "https://registry.npmjs.org/"
You can commit this to git. Tells Yarn to look for @swizec
-scoped packages on the NPM registry.
Deploy private NPM packages to Vercel or Netlify
Any collaborator can get access to your private packages with a NPM_TOKEN=...
environment variable. That includes Vercel, Netlify, and other deploy environments.
No other config necessary. Try making a new access token for each collaborator. They're free and the less reuse, the better.
Private GitHub packages
Github now offers private packages. You get a few with a free account and you'll need a paid account for serious use.
This is a great option because your company has a paid account. Right? Most do.
Takes more configuration than the NPM approach.
You'll need to create a personal access token with permission scopes for packages.
Then you add that token to your ~/.npmrc
file. This is the global .npmrc file, not in the project. Do not commit to git.
~/.npmrc
//npm.pkg.github.com/:_authToken=TOKEN
Then you tell NPM to use the GitHub registry for your package scope. In a local .npmrc
file that's added to git.
.npmrc
registry=https://registry.npmjs.org/ @swizec:registry=https://npm.pkg.github.com/
For Yarn that would be:
.yarnrc
"@swizec:registry" "https://registry.npmjs.org/"
You have to ensure your repository
field in package.json matches your GitHub project:
{
"repository": "git://github.com/swizec/private-package.git"
}
And then, you have to add a publishConfig
to your package.json.
{
"publishConfig": {
"registry": "https://npm.pkg.github.com"
}
}
You can now publish with npm publish
and install with npm install @swizec/private-package
.
Create a private package registry
You can go super private with a custom package registry.
Verdaccio looks promising as an on-premise registry host that you can run yourself. Gives you full control and whatnot.
I took one look at the Verdaccio docs, 3 looks at GitHub docs, and paid $7/mo for NPM. Ain't nobody got time for that.
Cheers,
~Swizec
Continue reading about Use private libraries to cleanup your codebase
Semantically similar articles hand-picked by GPT-4
- How JAMStack helps you ship
- Don't neglect your upgrades
- What I learned making my first open source React component
- This is Yak Shaving
- How to configure Jest with TypeScript
Learned something new?
Read more Software Engineering Lessons from Production
I write articles with real insight into the career and skills of a modern software engineer. "Raw and honest from the heart!" as one reader described them. Fueled by lessons learned over 20 years of building production code for side-projects, small businesses, and hyper growth startups. Both successful and not.
Subscribe below 👇
Software Engineering Lessons from Production
Join Swizec's Newsletter and get insightful emails 💌 on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.
"Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌"
Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.
Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.
Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.
Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev
Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization
Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections
Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog
Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com
By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️