5 Ways to Publish Multiple Packages in 2024

Leverage Bit, CI/CD Pipelines, Package Managers, Lerna or Yarn Workspaces to publish NPM Packages in 2024!

Lakindu Hewawasam
Bits and Pieces

--

If you’re an open-source developer or somebody that maintains third-party libraries in NPM, you likely know how complex it is to publish a library manually.

You’d need to set up an NPM CLI, and bump your package versions manually on your package.json files and then use publish commands to ship your library to an NPM repository. But, this is a tedious task to do in 2024. Instead, you should be looking into ways to improve your developer experience and reduce all manual work as much as possible.

So, I’d like to walk you through 5 ways in which you can publish an NPM Package in 2024.

Bit

One of the best tools to publish an NPM package is Bit. If you’ve not heard of Bit, it is a next generation build system for composable software. You can design, develop, build, test and version a component in isolation in its own independent space.

By doing so, you don’t couple your component to any project or repository, but rather treat it as its own independent entity.

Now, out of the box, Bit offers a powerful CI Server — Ripple CI that it uses to build a component tree. To understand this better, let’s look at the component tree illustrated below:

Here’s a component tree that I’ve created which shares code across a backend (AWS Lambda) and a frontend app (React).

Yes, with Bit, you can share code across frontend and backend!

Bit automatically tracks the usages of each component and creates this tree. When a change to a component happens, it will automatically trigger a build in Ripple CI and will propagate these changes up the component tree, ensuring that all components are using the latest versions.

Now, as you can understand, this is pretty powerful for NPM packages. You might have different NPM packages that rely on each other, and a change in one package might require updating all of its usages. That’s exactly what Bit can offer you.

Simply put, Bit lets you update multiple NPM packages at once!

Consider this scope that I hosted on Bit Cloud:

I’m maintaining two NPM packages:

  1. is-even
  2. logger

The logger is used by the is-even library. So, in theory, when logger updates, the is-even function should use the latest version of the logger as well and publish new versions to NPM. You can do this by customizing the build behavior on Ripple CI to enable publishing on NPM. You can configure this in under 5 minutes by making the following change to your Bit Workspace:

"teambit.workspace/variants": {
"*": {
"teambit.pkg/pkg": {
"packageJson": {
"packageManagerPublishArgs": [
"--access=public"
],
"private": false,
"name": "@{scope}/{name}",
"publishConfig": {
"scope": "@{scope}",
"registry": "https://registry.npmjs.org/",
"access": "public"
}
}
}
}
},

Next, all you’d have to do is:

  1. Create Node components and export them to your Bit Scope (must be named based on your NPM username).
  2. You’ll have to attach an NPM Auth Token onto Ripple CI.

This will automatically ship your Bit Components onto NPM with Ripple CI. To refer for a full implementation on this, check out my in-depth guide:

CI/CD Pipelines

Next, you can create your own CI/CD pipeline using tools like GitHub actions to automatically publish packages onto NPM whenever a Push or a Pull Request is Merged onto your production branch.

But, one key drawback here is that it doesn’t update only the packages that have a diff. Instead, it will publish a new version of all of your libraries regardless of it having a change or not.

So, to do this, I’d recommend using a mono-repo structure where you maintain one repo per package. But, do keep in mind that this creates a main drawback of added complexity in maintaining a mono-repo structure.

If you’re curious on finding out if you should use a mono-repo structure, check out this guide:

If you’re following a mono-repo structure, you can set up a GitHub actions file as follows:

name: Update and Publish NPM Packages

on:
push:
branches:
- main

jobs:
update-and-publish:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 20

- name: Install dependencies
run: npm install

- name: Update NPM packages
run: npm update

- name: Authenticate with NPM registry
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc

- name: Publish NPM packages
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Important: Make sure that you configure repository secrets for your NPM token.

If you’re using this exact workflow, it’ll update your NPM package whenever your make a push to your main branch.

Lerna

Lerna is a tool for managing JavaScript projects with multiple packages. It optimizes the workflow around managing multi-package repositories with git and npm.

It provides commands for bootstrapping, versioning, and publishing packages.

By using Lerna, you can ensure that you have:

  1. Atomic Releases: Changes to interdependent packages are released together, preventing compatibility issues.
  2. Automated Versioning: Automates the versioning of packages based on the commit history, making it easy to manage and track changes across packages.
  3. Efficient Dependency Management: Allows you to share common dependencies among packages, reducing duplication and optimizing storage.

To use Lerna to publish an NPM package, you’ll have to install Lerna:

npm install -g lerna

Next, initialize a Lerna workspace:

lerna init

Next, remember these three commands:

  1. lerna bootstrap: Installs dependencies and links packages.
  2. lerna run <script>: Executes a script in each package.
  3. lerna publish: Publishes updated packages.

Customize the lerna.json file to define project structure and behavior.

Yarn Workspaces

Yarn Workspaces is a feature of the Yarn package manager that allows you to manage multiple packages within a single codebase. It provides a way to create and manage dependencies between packages efficiently.

One of the biggest benefits of using Yarn Workspaces to update NPM packages is its support on monorepos. It simplifies managing multiple packages in a monorepo, allowing you to share dependencies and hoist common packages.

However, you necessarily can’t publish to NPM repositories with Yarn workspaces. Instead, Yarn Workspaces are primarily focused on efficient dependency management within a monorepo. But, you can leverage tools like Lerna and a Yarn Workspace together to publish your packages to NPM.

For an in-depth approach on this, check out this guide:

Package Managers

Finally, you can use the CLI locally to update your package. Though this is “old-school”, it still gets the job done.

You can install the NPM CLI locally and publish a package using npm publish. However, remember that using a Package Manager without any CI/CD offering is highly disadvantageous for many reasons:

  1. Manual Processes: Without CI/CD, many processes, such as testing, versioning, and deployment, need to be performed manually. This increases the likelihood of human errors and makes the process time-consuming.
  2. Lack of Automation: You miss out on the automation of repetitive tasks, leading to slower development and release cycles.
  3. Testing Challenges: Automated testing is integral to a robust release process. By publishing in a local environment, you may need to run tests manually, making it harder to ensure comprehensive test coverage.
  4. Inconsistent Releases: Manual processes can result in inconsistent release practices, making it challenging to maintain a standardized and reproducible release pipeline.
  5. Limited Rollback Capabilities: If you’re using a manual process to publish updates, you don’t have any record of a release to rollback on. So, if your new release creates errors, you have no choice but to fix it with a downtime.

If these drawbacks aren’t impactful to your project, feel free to stick to a manual process to publishing your NPM packages.

To publish an NPM package, first, ensure that your dependencies are up to date with this command:

npm update

Next, run tests to ensure the package is in a stable state using this command:

npm test

Aferward, bump the package version automatically using this command:

npm version [patch | minor | major]

[patch | minor | major] with the version update you want (patch for bug fixes, minor for new features, major for breaking changes).

Finally, release your package onto the NPM Registry using the command:

npm publish

Wrapping Up

This article explored five different ways to publish NPM packages in 2024. However, how do you select the right tool for you?

Well, based on the points discussed in this article, it is evident that using Bit is beneficial. Bit offers all the advantages that every other tool offers, but in a more simpler and straightforward manner. It lets you build your components in an independent space, and ship it to NPM while only updating the differences through its Ripple CI (for free).

I hope this article is helpful.

Thank you for reading!

--

--