In this article, you will learn to host a private NPM registry.
The attachment has two folders:
- The "package-example" - It is an example NPM package. I will publish it to the private registry.
- The "package-client" - It is an example NODE application. It will pull the example package from the private registry and use it in the "index.js" file.
The Private NPM Registry
There are many options to run a private NPM registry on your computer. In this note, I chose "Verdaccio". You can download Verdaccio and run it, you can also pull a docker image and run it in a container. In this note, I chose to use docker. If you are not familiar with docker, you can take a look at my earlier note.
docker pull verdaccio/verdaccio:4
By the time this note is prepared, the most updated Verdaccio version is 4. After pulling the Verdaccio image, we can start the container.
docker run -d --name verdaccio -p 4873:4873 verdaccio/verdaccio:4
To verify that the container is started, you can go to the URL - "http://localhost:4873/" to see the packages hosted in the registry. If you want the container to start when your computer starts, you can use "systemd" if you use a Ubuntu based computer. You can put a file named "verdaccio.service" in the "/etc/systemd/system" directory.
[Unit]
Description=Verdaccio npm registry service
After=docker.service
Wants=network-online.target docker.socket
Requires=docker.socket
[Service]
Restart=always
ExecStart=/usr/bin/docker container start -a verdaccio
ExecStop=/usr/bin/docker container stop -t 20 verdaccio
[Install]
WantedBy=multi-user.target
You can then manipulate the service by the following commands:
sudo systemctl start verdaccio.service
sudo systemctl stop verdaccio.service
sudo systemctl enable verdaccio.service
sudo systemctl disable verdaccio.service
sudo systemctl status verdaccio.service
Publish a Package
In the attached "package-example" folder, I have a simple NPM package defined by the "package.json".
{
"name": "@example/package-example",
"version": "1.0.0",
"description": "An example npm package",
"main": "index.js",
"author": "Song Li",
"license": "ISC"
}
You may notice that the package name is "@example/package-example". It is a scoped package. The scoped packages helps us to group packages in scopes. For example, the "@angular" scope groups all the angular packages. For simplicity, the "@example/package-example" package has a only a single "index.js" file to export a static string message.
module.exports = 'This is a string in the @example/package-example';
The "main" attribute in the "package.json" file tells node where to find the entry point of a NPM package.
- If package.json contains a
main
property, then use that. - If no main property, then try to load:
- index.js
- index.json
- index.node
To publish the package to the private registry, we can issue the following command in the "package-example" folder.
npm adduser --registry http://localhost:4873
npm publish --registry http://localhost:4873
- The "
npm adduser
" sets up the necessary credentials to the registry. Once succeeds, it saves the credentials in the ".npmrc" file in the user's home directory. We no longer need to provide credentials next time to publish a package to the registry; - The "
--registry
" attribute tells NPM which registry to use.
We can also put a ".npmrc" file in the package directory to associate the NPM scope and the registry.
@example:registry=http://localhost:4873/
With the local ".npmrc" file, we can then simply publish the package with the following command:
npm publish
To check if we have successfully published the package, we can issue the following command:
npm view @example/package-example versions
To un-publish the package, we can use the following command:
npm unpublish @example/package-example@1.0.0
Install the Package
In the attached "package-client" folder, I have an example node application that uses the "@example/package-example" package.
{
"name": "package-client",
"version": "1.0.0",
"description": "An example NPM package client",
"main": "index.js",
"author": "Song Li",
"private": true,
"license": "ISC",
"dependencies": {
"@example/package-example": "^1.0.0"
}
}
It is a simple node application in the "index.js" file to print out the static string in the "@example/package-example
" package.
const str = require('@example/package-example');
console.log(str);
In order to install the "@example/package-example" without specifying the "--registry
" attribute, we can place a ".npmrc" file in the local folder to associate the "@example
" scope and the registry URL.
@example:registry=http://localhost:4873/
We can then install the "@example/package-example" package and run the application.
npm install
node index.js
If everything goes well, we can see that the "@example/package-example" package is successfully installed from the private package and the application runs successfully.
Additional Note
By default, the docker container keeps the packages published to it in itself. In order to keep a backup of the packages, we can commit the container to an image. We can reference the "docker commit" documentation for details.
Points of Interest
- This is a note on how to host a private NPM registry.
- I hope you like my postings and I hope this note can help you one way or the other.
History
- 18th September, 2020: First revision