一、validate-npm-package-name 作用
顾名思义 validate-npm-package-name 验证包名称,那到底是不是呢?去Github看一下。
Github 地址:validate-npm-package-name
果然是的,接下来看下怎么使用。
1.1 内置规则
- 包名长度大于零
- 包名中的所有字符都必须是小写的,即不允许使用大写或混合大写的名称
- 包名可以由连字符(也就是
-)组成 - 包名不能包含任何非url安全字符(因为名称最终是url的一部分)
- 包名不能以
.或者_开头 - 包名称首尾不能有 空格
- 包名称不应包含以下任何字符:
~)('!* - 包名称不能与 node 核心模块名称相同 ,如
-
httpstream
-
fs
- 包名不能在黑名单内 黑名单:
node_modulesfavicon.ico - 包名称长度不能超过214
1.2 简单尝试下功能
验证名称
var validate = require("validate-npm-package-name")
validate("some-package")
validate("example.com")
validate("under_score")
validate("123numeric")
validate("@npm/thingy")
validate("@jane/foo.js")
上边的名称都是有效的,所以会返回以下对象
{
validForNewPackages: true,
validForOldPackages: true
}
试试规则不允许的名称
validate("excited!") // ! 不允许
validate(" leading-space:and:weirdchars") // url 处理 : 时不友好
可以看到返回值发生了变化,并且给出了原因。
{
validForNewPackages: false,
validForOldPackages: false,
errors: [
'name cannot contain leading or trailing spaces',
'name can only contain URL-friendly characters'
]
}
接下来走进源码的世界。
二、源码
2.1 怎么看?
看源码首先是要找到入口文件,一般都是根据 package.json文件的相关字段来找。
对于 package.json 文件其实有很多的字段配置,实在太多了,我也记不住,常用的也就那几个,这里没有找到 官方的文件规范, 贴个掘金的讲解:关于前端大管家 package.json,你知道多少?
1. main 字段
main 字段用来指定加载的入口文件,在 browser 和 Node 环境中都可以使用。
如果我们将项目发布为npm包,那么当使用 require 导入npm包时,返回的就是main字段所列出的文件的module.exports 属性。
如果不指定该字段,默认是项目根目录下的index.js。如果没找到,就会报错。
"main": "./src/index.js",
2 bin 字段
bin字段用来指定各个内部命令对应的可执行文件的位置,比如
"bin": {
"someTool": "./bin/someTool.js"
}
3 files 字段
files配置是一个数组,用来描述当把npm包作为依赖包安装时需要说明的文件列表。
当npm包发布时,files指定的文件会被推送到npm服务器中,如果指定的是文件夹,那么该文件夹下面所有的文件都会被提交。
"files": [
"LICENSE",
"Readme.md",
"index.js",
"lib/"
]
这里我们看看主角 validate-npm-package-name 的 package.json
源码已经找到,接下来一头扎进去看看。
2.2 分析源码
还记得当初使用这个包的时候是这个使用的
var validate = require("validate-npm-package-name")
validate("some-package")
从使用来看,我们需要找到默认导出
主角就是它了,点开发现里边都是一些判断,有些写的挺巧妙的,有些写的我有点看不懂(正则),看来以后还需要加强学习。
贴部分判断
var validate = module.exports = function (name) {
var warnings = []
var errors = []
// 名称不能为空
if (!name.length) {
errors.push('name length must be greater than zero')
}
// 名称首尾不能包含空格
if (name.trim() !== name) {
errors.push('name cannot contain leading or trailing spaces')
}
// 名称不能有大写
if (name.toLowerCase() !== name) {
warnings.push('name can no longer contain capital letters')
}
// 名称不能在黑名单内
blacklist.forEach(function (blacklistedName) {
if (name.toLowerCase() === blacklistedName) {
errors.push(blacklistedName + ' is a blacklisted name')
}
})
// 不能和 核心模块名称 冲突
builtins.forEach(function (builtin) {
if (name.toLowerCase() === builtin) {
warnings.push(builtin + ' is a core module name')
}
})
// ... 其他的一些判断
return done(warnings, errors)
}
var done = function (warnings, errors) {
var result = {
validForNewPackages: errors.length === 0 && warnings.length === 0,
validForOldPackages: errors.length === 0,
warnings: warnings,
errors: errors
}
if (!result.warnings.length) delete result.warnings
if (!result.errors.length) delete result.errors
return result
}
发现该库还是挺简单的(除了正则),从中学到了很多判断的技巧,例如:!name.length 以后在开发过程中应该也用得上
值得注意的是 引入了另外一个库 builtins , 看看他是干嘛的
2.3 builtins
Github地址:builtins
使用示例:
获取当前 Node.js 版本的核心模块列表:
var builtins = require('builtins')()
assert(builtins.indexOf('http') > -1)
获取特定 Node.js 版本的核心模块列表:
var builtins = require('builtins')({ version: '6.0.0' })
assert(builtins.indexOf('http') > -1)
```js
将实验模块添加到列表中:
```js
var builtins = require('builtins')({ experimental: true })
assert(builtins.indexOf('wasi') > -1)
好奇它是怎么做到的? 源码拉下来看看(虽然实力菜,可能看不懂,但是挡不住好奇心)
老规矩,去 package.json 里找入口文件
点开一看,好家伙,又引入了另外一个库,并且还发现了一个奇怪的写法。
先来看看这个奇怪的写法:
function Foo({
version = process.version,
experimental = false
} = {}) {
// do Something...
}
说实话,刚开始看不懂,群里问了问,突然顿悟,这不就是 函数的参数解构吗,如果没有传参数的话,就给解构的值设置默认值。
跑起来一看就明白了:
function Foo({
version = '1.0.0',
experimental = false
} = {}) {
console.log(version)
console.log('experimental: ', experimental);
}
Foo()
Foo({
version: '1.6.0',
experimental: true
})
学到了!666~
接下来回头看看 在 builtins 中引入的 semver 是啥东东。
GIthub地址:semver
npm 的语义化版本管理工具?然后就没了?没太明白继续查查资料。
网上找啊找,找到了一个应该是官方的文档。
简单来说就是一套规范,用于规范 项目的版本号的。
这个库 实现了跟版本控制有关的一些方法,如:
- 比较两个版本号的大小
- 验证某个版本号是否合法
- 提取版本号,例如从“=v1.2.1”体取出"1.2.1"
- 分析版本号是否属于某个范围或符合一系列条件
嗯,本次学习源码就差不多了,接下来做个总结
三、总结
- 复习了
package.json各个配置字段的作用 - 学到了很多实用的判断方法
- 知道了 通过
builtins库可以获取到指定版本的Node核心模块列表 - 知道了
semver语义化版本控制规范,以及里边的一些细节,目前还记不住,需要下来多看看尽量能把一些赏识性的规则记下来。
四、 需要帮助
- 目前没找到
package.json的官方文档,求助!
文中提到的仓库及相关参考:
- Github validate-npm-package-name
- Github builtins
- Github semver
- SemVer文档 语义化版本控制规范 2.0.0