To accept 1.3.0-beta.1, write ^1.3.0-beta.1. ^1.2.3 skips it even though 1.3.0-beta.1 sorts between 1.2.3 and 2.0.0, because node-semver, the range engine npm uses, lets a prerelease satisfy a range only when a comparator in the range names a prerelease with the same major, minor and patch. ^1.2.3 names none.
The rule in action
^1.3.0-beta.1 means >=1.3.0-beta.1 <2.0.0 and names a prerelease of 1.3.0, so later 1.3.0 prereleases get in and those of any other version don’t:
1.2.3 no below the floor
1.3.0-beta.1 yes
1.3.0-beta.2 yes
1.3.0-rc.1 yes rc sorts after beta
1.3.0 yes
1.4.0-beta.1 no a prerelease of 1.4.0, which the range doesn't name
1.9.9 yes the highest match
2.0.0-rc.1 no
Opting into one beta isn’t opting into the next version’s betas. node-semver’s README gives the reason: prereleases often break things between one another, and choosing 1.3.0-beta.1 accepts that risk for 1.3.0 only. Once 1.3.0 ships, the range takes releases up to 2.0.0 like any caret.
includePrerelease
node-semver’s includePrerelease option turns the rule off and treats prereleases like any other version:
semver.satisfies('1.3.0-beta.1', '^1.2.3') // false
semver.satisfies('1.3.0-beta.1', '^1.2.3', { includePrerelease: true }) // true
npx semver -p -r '^1.2.3' 1.2.3 1.3.0-beta.1 2.0.0-rc.1 # prints 1.2.3 and 1.3.0-beta.1
2.0.0-rc.1 stays out even then: the caret’s top bound is <2.0.0-0, below every 2.0.0 prerelease. npm has no setting for the option, so npm install and npm update always apply the rule, and so does this tool.
Gotchas
^1.0.0-0is not “every 1.x prerelease”. It’s sometimes suggested for that, npm’s own install docs among others, but it names a prerelease of 1.0.0 only:1.3.0-beta.1doesn’t match it.*and1.xskip prereleases too. No range admits one without naming it.- Pin a beta by its full version.
npm install [email protected]installs exactly that prerelease; a dist-tag such asnext(if the package publishes one) installs whatever the tag points to.
Cargo and Composer
Cargo works the same way: requirements exclude prereleases unless one is asked for, and "1.0.0-alpha" allows later 1.0.0 prereleases and releases, but not 1.0.1-alpha. Composer filters by stability instead: minimum-stability defaults to stable, and a flag such as @beta on one constraint lets that package in at a lower stability.