npm的dependencies(http,git,ssh)

作者:ManfredHu
链接:http://www.manfredhu.com/2019/04/25/47-npm-dependencies/index.html
声明:版权所有,转载请保留本段信息,谢谢大家

npm version

版本号

npm install xxx 大家都知道,一般版本号会以类似1.2.3这样三位表示,具体的,第一位的1表示主版本号major,第二位是次版本号minor,第三位是修补版本patch。
比如vue的package.json有这么一段

1
2
3
4
5
6
7
8
9
{
"devDependencies": {
"typescript": "^3.1.3",
"webpack": "~4.28.4",
"weex-js-runtime": "^0.23.6",
"weex-styler": "^0.3.0",
"yorkie": "^2.0.0"
}
}

其中,webpack的版本为"~4.28.4",前面的波浪号与其他的^确实不同。

版本号前缀^和~的区别

^~的区别如下

  • ~会匹配最近的小版本依赖包,比如~4.28.4会匹配所有4.28.x版本,但是不包括4.29.x
  • ^会匹配最新的大版本依赖包,比如^3.1.3会匹配所有3.x.x的包,包括3.2.0,但是不包括4.0.0

自动升级最后一位版本号可以看我之前写的npm version升级版本号

模块名和命令行执行命令不一定一样

写过npm模块的同学会发现,大部分的命令行全局模块,如vue跟npm的模块名是一样的,都是vue。但是有的是不一样的,比如
egg-ts-helper提供的生成ts类型的辅助工具,命令行为ets,是通过package.json的bin属性来定义的。如果这里定义了一样的就是一样的命令,但是偏偏有的名字长的不一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"name": "egg-ts-helper",
"version": "1.25.2",
"description": "egg typescript helper",
"bin": {
"ets": "dist/bin.js"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"repository": {
"type": "git",
"url": "git@github.com:whxaxes/egg-ts-helper.git"
}

依赖dependencies

devDependencies

如字面意思,这个是开发时候用到的依赖,比如代码格式化,美化,编译相关的。反正代码运行没用到的都会在这里。可以用下面两个指令安装依赖,命令等价

1
2
npm i xxx --save-dev
npm i xxx -D

如果是下面的命令,通常是一些CI程序,会强制区分生产环境和其他环境,不会安装devDependencies的依赖

1
npm i --production

dependencies

这个是运行时候的依赖,如下命令会安装依赖到这里。其实npm可以支持很多种写法

1
2
3
4
5
6
7
8
9
10
npm install (with no args, in package dir)
npm install [<@scope>/]<name>
npm install [<@scope>/]<name>@<tag>
npm install [<@scope>/]<name>@<version>
npm install [<@scope>/]<name>@<version range>
npm install <git-host>:<git-user>/<repo-name>
npm install <git repo url>
npm install <tarball file>
npm install <tarball url>
npm install <folder>

举个例子,如下安装的是react指定的版本,当然你也可以指定git仓库

1
2
3
npm install react@16.8.3
npm install facebook/react@16.8.3
npm install https://github.com/facebook/react.git

特别的,某些CI程序,只会安装dependencies的依赖

1
npm i --production

git url的组成

1
<protocol>://[<user>[:<password>]@]<hostname>[:<port>][:][/]<path>[#<commit-ish> | #semver:<semver>]

一个完整的git url组成如上就是这么复杂。protocal有httpsgitgit+ssh,git+https。如下是官方给出的几个例子和几个我测试的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 具体版本分支
git+ssh://git@github.com:npm/cli.git#v1.0.27
# 主版本
git+ssh://git@github.com:npm/cli#semver:^5.0
# https链接
git+https://isaacs@github.com/npm/cli.git
# git协议
git://github.com/npm/cli.git#v1.0.27
# 具体到git的commitId
git://github.com/ManfredHu/someExercise.git#7813e8d9879add108b2c04944f529d1bdbbe41f2
# 具体到哪个分支
git://github.com/ManfredHu/someExercise.git#js
# 具体到某个版本号
git+https://github.com/vuejs/vue.git#semver:2.5.21

如果是ssh,需要在账号加上ssh-key生成的公钥。
如果是https或者http可以指定账号密码,比如我的账号是abc,密码是cba,那么链接就是git+https://abc:cba@github.com/vuejs/vue.git#semver:2.5.21

私密包安装形式的介绍

我们知道npm包是公开的,比如npm是对整个互联网公开,cnpm淘宝是对阿里整个集团公开,腾讯tnpm是对整个腾讯内网公开。
但是如果你做的是很私密的业务,不希望把npm包公开,那么还有啥好方法组织你的代码呢?再举个例子,npm包是公用的,如果这个npm包只有你一个人用,你还需要发npm包吗?

我们可以有几种方法来构建一个非npm包形式的工程,会在执行npm i的时候区拉取模块代码,如上面几个链接的话拉取速度会偏慢,但是因为每次拉取到的代码是最新的,一些潜在的bug会修复。最近在做基于egg+ts结合protobuf与后台通信的时候,在选型的时候出现了几个选择,因为我们项目有类似git://github.com/ManfredHu/someExercise.git#js的外部pb协议生成egg的service需求,所以没有基于发布npm包的形式安装了几个npm包。很绕但是比较真实,我们不希望我们的协议文件暴露出去,npm包大家都可以拉。但是协议这块希望是私密的,没有权限是拉不到的。

CI过程依赖包安装的几种方法

思考后,有下面几种方法

  • ssh-key
  • http或者https 配合 公共账号
  • 项目写死公共账号的账号和密码

分析一下,ssh-key的形式,在CI的时候会很蛋疼,因为CI部分是在独立的docker容器上的,如果这个docker容器配置了公共的账号并且生成ssh-key加入了账号还好,但如果像我们这边一样没有的话就非常蛋疼了。如果可能推荐走这种形式

第二种是http或者https 配合 公共账号,也是我们现在用的,速度会比ssh的慢但是还能用。遇到项目嵌套的话,也是非常蛋疼,原因请看第三种

第三种不推荐,一个原因是账号密码在代码里面,泄露源码会非常麻烦,第二个原因是如果遇到A项目嵌套B项目,B项目嵌套C项目,你在A项目写了账号密码的依赖,B项目可以拉了,但是B项目依赖了C项目也需要写上账号密码,否则拉不下来。也就是说账号密码这种形式,全部依赖仓库都需要写上账号密码,否则会报npm install失败,具体原因也很难从错误提醒看出来

参考


Copyright © 2015 - 2019 ManfredHu胡文峰的个人博客

All rights reserved. Designed and powered by ManfredHu.

粤ICP备18133029号