При выполнении некоторых команд вы когда-нибудь сталкивались с сообщением о том, что версия слишком низкая и вам нужно обновить версию?Какие правила используются для ограничения и сопоставления номера версии? semver — это модуль управления семантическими номерами версий, который может анализировать и сравнивать номера версий и стандартизировать формат номеров версий.
Основные правила нумерации версий
структура
Номер версии обычно состоит из трех частей, начиная с.
разделенный, какX.Y.Z
,в
- X: основной номер версии, несовместимые большие изменения
- Y: дополнительный номер версии, функциональные изменения
- Z: номер версии, исправления ошибок
Каждая часть является целым числом (>=0) и изменяется в соответствии с инкрементными правилами.
Дополнительную информацию можно добавить после номера версии, используя-
подключение, например:
- XYZ-Альфа: закрытая бета-версия
- XYZ-бета: общедоступная бета-версия
- XYZ-Stable: стабильная версия
правила области действия
существуетpackage.json
В файле зависимостей, которые мы устанавливаем, будет описание номера версии, например, если реактивный проект инициализирован, в егоpackage.json
автоматически устанавливаемые зависимости
"devDependencies": {
"react": "^15.6.1",
"react-dom": "^15.6.1"
}
На самом деле номера версий, которые мы обычно видим, не только^
префикс и~
, так что они означают?
^
: Разрешить без изменений [основных, несовершеннолетних, патч] с первого изменить количество ненулевых (совпадений больше, чем x, y, z Обновление y, номер версии z)
существуетX.Y.Z
В номере версии структуры все неотрицательные целые числа X, Y и Z. Приведенное выше определение означает, что слева направо первое ненулевое число не может быть изменено, а следующее число может быть изменено для пример:
- X, Y, Z не равны 0,
^15.6.1"
, крайняя левая ненулевая цифра15
, поэтому X не разрешено обновлять, то есть основной номер версии не будет превышать 15, что означает номер версии>=15.6.1 && <16.0.0
- Если x равно 0, то первое ненулевое число y, и только z может быть изменено,
^0.1.2
Указывает номер версии>=0.1.2 && < 0.2.0
- Если числа X и Y оба равны 0, первым ненулевым числом будет Z, что означает, что номер версии не может быть обновлен;
^0.0.2
, номер основной версии и номер дополнительной версии равны 0, а номер версии не равен нулю, что означает номер версии>=0.0.2 && < 0.0.3
~
: соответствует больше чемX.Y.Z
ОбновитьZ
номер версии
- X, Y, Z не равны 0,
~1.2.3
Указывает номер версии>=1.2.3 && < 1.3.0
- Х равно 0,
~0.2.3
Указывает номер версии>=0.2.3 && < 0.3.0
,В этой ситуации,~
Эквивалентно^
- X и Y равны 0,
0.0.3
Указывает номер версии>=0.0.3 && < 0.1.0
x
: Может заменить любой из X, Y, Z, указывая, что положение может быть обновлено.
-
1.2.x
:>=1.2.0 && < 1.3.0
-
1.x
:>=1.0.0 && < 2.0.0
-
*
: любая версия может быть
надx
Можно использовать*
Вместо этого, на самом деле, используйтеx
или*
можно опустить или не писать, например1.2.x
а также1.2
означает то же самое
-
: диапазон, содержащий номер первой версии и номер второй версии представляет собой замкнутый интервал,-
Оба диапазона номеров версий для соединения включают
-
0.1.0
-2
:>=0.1.0 && < 3.0.0
-
0.1.0
-2.1.1
:>=0.1.0 && <= 2.1.1
Установить
npm install semver
Применение
// 引入模块
const semver = require('semver')
semver.clean(' =v1.1.1 ');// 1.1.1,解析版本号,忽略版本号前面的符号
semver.valid('1.1.1'); // true,版本号是否合法
semver.valid('a.b.c'); // false
semver.satisfies('1.2.4', '1.2.3 - 1.2.5'); // true, 判断版本是否在某个范围
Здесь перечислены только некоторые из вариантов использования, а конкретные можно найти вДокументацияПосмотреть в.
Принцип реализации
Прочитав исходный код semver, я разобрался в принципах реализации некоторых методов.
clean
...
exports.clean = clean;
function clean(version, loose) {
// 替换参数中的空格和符号
var s = parse(version.trim().replace(/^[=v]+/, ''), loose);
return s ? s.version : null;
}
...
valid
...
exports.valid = valid;
function valid(version, loose) {
var v = parse(version, loose);
return v ? v.version : null;
}
...
clean
а такжеvalid
использовал методparse
, этот метод используется для анализа номера версии, чтобы проверить, является ли он стандартизированным, и, наконец, вернуть стандартизированный формат
parse
Проанализируйте формат номера версии, чтобы определить, является ли он допустимым или нет.Этот метод используется при реализации многих методов.
exports.parse = parse;
function parse(version, loose) {
if (version instanceof SemVer)
return version;
if (typeof version !== 'string')
return null;
if (version.length > MAX_LENGTH)
return null;
// 是否应用宽松模式
var r = loose ? re[LOOSE] : re[FULL];
if (!r.test(version))
return null;
try {
return new SemVer(version, loose);
} catch (er) {
return null;
}
}
/*
* 参数中的loose表示是否宽松检查版本号
* loose为true的时候,检查版本号的格式不会那么严格
* 比如定义数字标识符,就定义了一种宽松的匹配模式
* /
// ## Numeric Identifier
// A single `0`, or a non-zero digit followed by zero or more digits.
var NUMERICIDENTIFIER = R++;
src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; // 单个0或者0后面跟着0个或多个不为0的数字
var NUMERICIDENTIFIERLOOSE = R++;
src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; // 0-9的1位或多位数字
satisfies
exports.satisfies = satisfies;
function satisfies(version, range, loose) {
try {
// Range会判断输入的范围是否合法,并返回一个格式化之后的range
range = new Range(range, loose);
} catch (er) {
return false;
}
return range.test(version);
}
satisfies
называетсяRange
, который нормализует диапазон пользовательского ввода
exports.Range = Range;
function Range(range, loose) {
if (range instanceof Range) {
if (range.loose === loose) {
return range;
} else {
return new Range(range.raw, loose);
}
}
if (range instanceof Comparator) {
return new Range(range.value, loose);
}
if (!(this instanceof Range))
return new Range(range, loose);
this.loose = loose;
/*
* 将范围按照‘||’分开
* 对每个范围进行解析,并且过滤出没有意义的范围
*/
// First, split based on boolean or ||
this.raw = range;
// 用split将输入的范围划分成数组
this.set = range.split(/\s*\|\|\s*/).map(function(range) {
// 对数组的每一项进行解析
return this.parseRange(range.trim());
}, this).filter(function(c) {
// throw out any that are not relevant for whatever reason
return c.length;
});
if (!this.set.length) {
throw new TypeError('Invalid SemVer Range: ' + range);
}
this.format();
}
/*
* 对用户输入的范围进行解析检验,返回规范的格式
*/
Range.prototype.parseRange = function(range) {
var loose = this.loose;
range = range.trim(); // 去掉前后的空格
debug('range', range, loose);
// 判断是否是宽松模式,并应用‘连字符’的正则去匹配替换
// 将连字符的形式替换成比较符号的形式,`1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4
var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE];
range = range.replace(hr, hyphenReplace);
debug('hyphen replace', range);
// `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace);
debug('comparator trim', range, re[COMPARATORTRIM]);
// `~ 1.2.3` => `~1.2.3`
range = range.replace(re[TILDETRIM], tildeTrimReplace);
// `^ 1.2.3` => `^1.2.3`
range = range.replace(re[CARETTRIM], caretTrimReplace);
// 将表示范围的字符串的多个空格替换成一个空格
range = range.split(/\s+/).join(' ');
// At this point, the range is completely trimmed and
// ready to be split into comparators.
var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
// 将表示范围的字符串按照空格划分为数组,对每一个数组向进行解析检验,返回规范的表示并重新连接成字符串
var set = range.split(' ').map(function(comp) {
return parseComparator(comp, loose);
}).join(' ').split(/\s+/);
if (this.loose) {
// 在宽松模式下,过滤掉所有不合法的比较器
set = set.filter(function(comp)
return !!comp.match(compRe);
});
}
set = set.map(function(comp) {
return new Comparator(comp, loose);
});
return set;
};
/**
* 将规范后的范围字符串重新连接起来并返回
*/
Range.prototype.format = function() {
this.range = this.set.map(function(comps) {
return comps.join(' ').trim();
}).join('||').trim();
return this.range;
};
Ссылаться на:документация несколько исходный адрес