5

Introduction to managing a private NPM registry with Verdaccio

 1 year ago
source link: https://wanago.io/2023/07/24/verdaccio-private-npm-registry/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Introduction to managing a private NPM registry with Verdaccio

JavaScript Node.js

July 24, 2023

An organization often develops more than one project. Since the projects are often part of a more extensive ecosystem, this could lead to duplicating some of the code. To deal with this problem, we can create JavaScript libraries that we can reuse across various projects.

The most straightforward way of maintaining packages available in all our projects would be to publish them to npmjs.com. Unfortunately, this is probably not a viable solution unless our organization develops open source. Fortunately, we can maintain a private NPM registry. In this article, we use Verdaccio to publish JavaScript libraries so that they are available only to our organization.

Introducing Verdaccio

Verdaccio is a free and self-hosted NPM registry. It means that we need to maintain it by running it locally or deploying it to the cloud.

The most straightforward way of installing it is through NPM.

npm install --global verdaccio

Once we do the above, we can run verdaccio in our terminal.

Screenshot-from-2023-07-23-21-11-34.png

Now, Verdaccio is available at http://localhost:4873. Let’s create our first package and publish it.

Creating and publishing a package

To create a new package, we need to initialize a new npm project in an empty directory.

npm init -y

Wrote to /home/marcin/Documents/Projects/sum/package.json:

  "name": "sum",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  "keywords": [],
  "author": "",
  "license": "ISC"

Let’s create a straightforward function that we can reuse in another project.

index.js
function sum(numberOne, numberTwo) {
  return numberOne + numberTwo;
module.exports = sum;

To publish our library, we should create a user in our registry first. We can do that with the npm adduser command.

npm adduser --registry http://localhost:4873/

Once we provide credentials, we are logged in to our registry, and we can publish the library.

npm publish --registry http://localhost:4873

Our package now has a dedicated web page that we can view to see its details.

Screenshot-from-2023-07-23-21-54-39.png

An important thing above is that Verdaccio detects some versions of our library published years ago. This is because there already is a library called sum on npmjs.com. Because of that, it is worth prefixing the libraries of our organization when naming them, for example, @wanago/sum.

Installing packages

We will run into an issue when we try installing our package in another project.

npm install [email protected]

npm ERR! code ETARGET
npm ERR! notarget No matching version found for [email protected].
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn’t exist.

Installing our library fails because the npm installed on our machine is unaware of our private registry. By default, npm uses the npm public registry that does not contain the library we created.

Running npm install sum right now without specifying the version would install the sum library with version 0.1.4 from npmjs.com.

To fix this problem, let’s use our private registry.

npm set registry http://localhost:4873/ --location project

This creates the .npmrc file that contains the address of our registry.

.npmrc
registry=http://localhost:4873/

Now, when we install a package using npm, it will first check if we have it in our private registry.

npm install sum

Creating a TypeScript library

So far, we’ve created a Node.js package that uses CommonJS modules and imported it into a Node.js project. A more advanced case is creating a TypeScript library that we can use both in a JavaScript and TypeScript project. To achieve that, we need to build our TypeScript library before publishing it.

We need to start by initializing a new npm project in an empty dictionary and installing TypeScript.

npm init -y
npm install typescript

The next step is to define a TypeScript configuration.

tsconfig.json
  "compilerOptions": {
    "strict": true,
    "module": "commonjs",
    "target": "es2015",
    "declaration": true,
    "outDir": "./dist"
  "include": ["index.ts"]

Feel free to expand the above configuration with more properties as you see fit.

Some of the important parts of the above configuration are:

  • module  – we use CommonJS here because it is the format most libraries on NPM use. While we could deliver our code using multiple module types, let’s keep it simple for now.
  • declaration – thanks to setting this, TypeScript will create the types declaration file,
  • outDir – this configures the TypeScript compiler to output the code in the directory we choose,
  • include – with this array, we can specify which files we want to include when compiling.

Let’s create the index.ts file that contains our library.

index.ts
export function multiply(numberOne: number, numberTwo: number) {
  return numberOne * numberTwo;

Now, we can use our TypeScript config in our package.json file.

package.json
  "name": "@wanago/multiply",
  "version": "1.0.0",
  "description": "",
  "types": "./dist/index.d.ts",
  "main": "./dist/index.js",
  "scripts": {
    "build": "tsc -p ./tsconfig.json"
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "typescript": "^5.1.6"

When we run the npm run build command, TypeScript creates the dist directory. We need to point the main and types properties in our package.json to the correct files.

Once we have our build, we can publish the library.

npm publish --registry http://localhost:4873

Using the library in a TypeScript project

It’s straightforward to use our library in a project that uses TypeScript. After running npm install @wanago/subtract, we can import our library.

import { multiply } from '@wanago/multiply';
console.log(multiply(10, 5)); // 50

Using the library in a Node.js project without TypeScript

Thanks to compiling our TypeScript code to CommonJS modules, we can use our library without any issues in a Node.js project that does not use TypeScript.

const { subtract } = require('@wanago/multiply');
console.log(subtract(5, 5)); // 25

Publishing a new version

A library usually contains more than one function. A common way of structuring a library is creating a separate file per function.

multiplyMultipleNumbers.ts
export function multiplyMultipleNumbers(numbers: number[]) {
  return numbers.reduce((result, nextNumber) => {
    return result * nextNumber;
  }, 1);

We also need to decide which functions we want to make available by exporting them from our index.ts file.

index.ts
export { multiply } from './multiply';
export { multiplyMultipleNumbers } from './multiplyMultipleNumbers';

Once we modify our library, we need to build it again by running npm run build. Before publishing, we need to alter the version specified in our package.json file.

package.json
  "name": "@wanago/multiply",
  "version": "1.1.0",
  "description": "",
  "types": "./dist/index.d.ts",
  "main": "./dist/index.js",
  "scripts": {
    "build": "tsc -p ./tsconfig.json"
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "typescript": "^5.1.6"

It is very important to maintain the Semantic Versioning approach. If you want to know more, check out Keeping your dependencies in order when using NPM

We can now run the npm publish --registry http://localhost:4873 command and publish the new version of our library. We also need to update it in the project that uses it.

"@wanago/multiply": "^1.1.0"

Once we do that, we can use the latest version of our library.

import { multiply, multiplyMultipleNumbers } from '@wanago/multiply';
console.log(multiply(10, 5)); // 50
console.log(multiplyMultipleNumbers([2, 4, 10])); // 80

Summary

In this article, we’ve gone through the idea of managing a private NPM registry with Verdaccio. We learned how to install it locally on our machine and publish both JavaScript and TypeScript libraries. While this serves as a good introduction to Verdaccio, there are still many things to cover, such as maintaining our registry in the cloud, so stay tuned!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK