Skip to content

Instantly share code, notes, and snippets.

@tfennelly
Last active October 13, 2020 13:37
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tfennelly/f1d573d935f4e9e9b4d1ee1b0ab6c04c to your computer and use it in GitHub Desktop.
Save tfennelly/f1d573d935f4e9e9b4d1ee1b0ab6c04c to your computer and use it in GitHub Desktop.

Publishing pre-release versions of an NPM package

There are times when we want to be able to publish pre-release (ala SNAPSHOT in maven terminology) versions of NPM packages to the NPM registry. We want to do this so as to provide these pre-release versions to CI builds of other dependant components etc. But what we do NOT want is for these pre-release packages to be unknowingly installed by someone that simply runs npm install <packagename> (i.e. does not specify an @<version> suffix).

Key Concepts

Here are the key things you need to understand in order to be able to publish pre-release versons of packages:

  1. By default, the npm publish command publishes the package and gives a tag of latest to the version in the package.json, overwriting the lasts latest tag version.
  2. By default, the npm install command installs the package version that has the latest tag.

See the dist-tag command for more details on this.

Howto

It's actually quite simple. Imagine you have a package named sometestpackabc and it has package.json as follows (removed parts that are not relevant).

{
  "name": "sometestpackabc",
  "version": "1.0.2",
}

After running npm publish we run npm dist-tag and can see that the latest tag version is 1.0.2.

tfennelly@diego:~/zap/sometestpackabc
$ npm publish
+ sometestpackabc@1.0.2
tfennelly@diego:~/zap/sometestpackabc
$ npm dist-tag ls sometestpackabc
latest: 1.0.2

If I now run npm install sometestpackabc in another package, version 1.0.2 will be installed as it is the version having the latest tag.

I make changes to sometestpackabc and want to preform a "beta1" pre-release of it so as to provide it to some other component. The package.json looks as follows (note the -beta1 suffix).

{
  "name": "sometestpackabc",
  "version": "1.0.3-beta1",
}

The trick here is in the execution of the npm publish command. You need to use --tag so as to give the newly published pre-release version a tag different to the default (i.e. latest), and so stopping npm install commands from installing it.

$ npm publish --tag=beta1
+ sometestpackabc@1.0.3-beta1
tfennelly@diego:~/zap/sometestpackabc
$ npm dist-tag ls sometestpackabc
beta1: 1.0.3-beta1
latest: 1.0.2
tfennelly@diego:~/zap/sometestpackabc
$

Now if someone runs plain npm install, they will install version 1.0.2 because it has the latest tag. But, the dependant components that you'd like to test the new pre-release version can explicitly depend on the 1.0.3-beta1 version, forcing it to be installed by its CI build.

@sophistifunk
Copy link

Dude this is awesome. Could we use ticket numbers for the snapshot versions/tags?

@tfennelly
Copy link
Author

@sophistifunk not sure about that. I do know that you can NOT use a valid semver (yes, I said "NOT" :) ).

Another thing I don't know is the effect of having too many tags. I see there's an npm dist-tag rm command, making me assume they'd prefer tags to be removed once they are obsolete, but maybe it's just so as to help keep npm dist-tag ls in a usable state.

I was actually thinking that maybe just use the same tag the whole time e.g. beta :)

@scherler
Copy link

nice

@sophistifunk
Copy link

@tfennelly are you happy for me to copy + paste this excellent writeup to the CB dev resources wiki?

@tfennelly
Copy link
Author

@sophistifunk sure go for it

(sorry for the late reply)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment