公司的前端项目零散,各个项目间有大量耦合严重的业务代码。基于这个背景,考虑建立一个私有的npm仓库来存储一些常用的工具函数、配置文件、以及一些常用的业务逻辑。本文选用Sinopia来搭建私有的npm仓库。使用PM2来管理Sinopia进程。
登录公司的开发机后,全局安装Sinopia
npm install --global sinopia
然后我们创建一个sinopia的配置文件 用来定义一些参数
$ vim sinopia.config.yaml
首先,我们来看看sinopia的完整的配置文件
其中,比较重要的包含几个配置
- users
- uplinks
- packages
- listen
users
这个配置项决定了我们使用什么账户来拥有这个NPM的权限
完整实例为
1 users:
2 admin:
3 # crypto.createHash('sha1').update(pass).digest('hex')
4 password: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
其中 第二行表示用户名,这边我们使用默认的admin,也可以使用自定义的用户名
第三行表示第四行的password是如何生成的 也就是说,password配置项的密码是由sha1算法生成的,我们只要记住加密前的密码,填写加密后的密文就可以了。
第三行的密码生成是用Nodejs的crypto模块生成的,我们只要把我们的密码作为参数传入update函数(也就是pass变量的位置)生成就可以了
$ node
> crypto.createHash('sha1').update('我想要的密码').digest('hex')
'24c19e31419eebc186b72f8fd85a04de010a5e86' // 生成的密文
将上述密文填入sinopia.config.yaml的users > admin > password字段即可
uplinks
我们的私有库仅有我们自己上传的包 而npm只能注册一个源的机制导致我们必须通过私有库来请求公共的包 比如我们需要安装jQuery,而我们的私有库没有。那么私有库就会去公网上请求。uplinks就是类似一个别名的列表,给公网的包仓库取一个别名,用于更加方便的调用。
uplinks:
npmjs: // 这边我们定义npm的仓库 也可以定义cnpm等不同的源作为公共仓库
url: https://registry.npmjs.org/
packages
这是权限相关的配置项 定义可读 可写的范围
packages:
'*':
# 允许所有用户读取包,包括未认证用户 (如果使用的是公网ip的机器 需要考虑相关的安全问题,
# 编者使用的是内网机器,没有这方面太大的问题。)
# 你可以指定用户名以及组名,需要依赖auth插件以及相关的关键字"$all", "$anonymous",
# "$authenticated",本文暂不考虑这种情况,如有需要,可以查看相关文档
access: $all // 所有用户可读
publish: admin // admin用户可写,这取决与你的users字段
# 如果私有仓库中没有想要的包,请求将会代理到对应的公共仓库
# 取决与定义的uplinks字段
proxy: npmjs
listen
定义一些监听的端口号,域名等配置
由于默认定义的域名为localhost,这将导致内网无法访问
所以必须至少修改为0.0.0.0或者可用的IP地址
listen:
0.0.0.0:4873 // IP:端口号
# - localhost:4873 # default value
# - http://localhost:4873 # same thing
# - https://example.org:4873 # if you want to use https
# - [::1]:4873 # ipv6
# - unix:/tmp/sinopia.sock # unix socket
以上四个就是一些基本的配置项 将这些配置项填入sinopia.config.yaml之后 我们来看看最终输出的文件
// sinopia.config.yaml
1 storage: ./storage
2
3 listen:
4 0.0.0.0:4873
5
6 users:
7 admin:
// crypto.createHash('sha1').update('我想要的密码').digest('hex')
8 password: 24c19e31419eebc186b72f8fd85a04de010a5e86
9
10 packages:
11 '*':
12 access: $all
13 publish: $all
14 proxy: npmjs
15
16 uplinks:
17 npmjs:
18 url: https://registry.npm.taobao.org/ // 使用的淘宝源
启动
当我们填写好配置文件之后,键入sinopia -c ./sinopia.config.yaml的命令后 sinopia便运行起来了
在我们自己的浏览器中 键入sinopia运行所在的主机地址以及端口号 x.x.x.x:4873 便能看到私有仓库的界面了
$ sinopia -c ./sinopia.config.yaml // 前台运行
点击右上角的login 填入你在配置文件中的账号和密码,就能验证用户名密码是否符合预期
后台启动
现在有个问题 就是直接使用sinopia -c ./sinopia.config.yaml命令启动 那么sinopia程序就只在前台启动 如果退出进程或者退出命令行 sinopia就会停止运行,这无法接受。 所以我们将使用PM2工具来启动sinopia
PM2是一个进程管理工具 使用PM2 您的应用将达到持久化,在崩溃和机器重启时自启动。所有的应用都被守护进程,例如,在后台持续运行。PM2相关本文将不再介绍 具体可查看PM2官方文档
使用PM2管理sinopia非常简单 安装PM2后运行sinopia脚本即可
首先 安装PM2
$ npm install pm2 -g
$ pm2 -v // 安装完毕后检查是否安装成功
然后 创建一个sinopia运行脚本
$ vim sinopia.start.sh
// sinopia.start.sh
1 sinopia -c ./sinopia.config.yaml
保存退出后 使用pm2指令来运行sinopia
$ pm2 start ./sinopia.start.sh --name="sinopia" // 给这个进程取一个sinopia的别名
$ pm2 list // 如果看到启动的sinopia那么说明后台启动成功了。
┌────────────────┬────┬─────────┬──────┬───────┬────────┬─────────┬────────┬──────┬───────────┬──────┬──────────┐
│ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
├────────────────┼────┼─────────┼──────┼───────┼────────┼─────────┼────────┼──────┼───────────┼──────┼──────────┤
│ sinopia │ 10 │ N/A │ fork │ 1629 │ online │ 0 │ 2D │ 0% │ 1.2 MB │ root │ disabled │
└────────────────┴────┴─────────┴──────┴───────┴────────┴─────────┴────────┴──────┴───────────┴──────┴──────────┘
发布包 && 获取包
当我们配置好服务端的npm私有仓库后,我们需要配置本地的机器来接入私有的仓库
获取包
由于获取包的权限是所有人可读
那么我们仅需将npm的源修改为私有仓库的地址即可
$ npm config set registry http://xx.xx.xx.xx:4873
配置好之后,依赖的安装将走内网的仓库,如果内网的仓库没有需要的包 那么将会代理到配置的公共仓库中。
发布包
本段仅介绍私有仓库的发布相关 涉及具体发布npm包的流程不再赘述
上传包的权限为x用户(x用户即为配置文件中的users字段配置的信息) 那么就需要先登录后在上传
如果没有修改过源 那么同样得修改npm仓库源 当然 配置过一次就可以了
$ # npm config set registry http://xx.xx.xx.xx:4873 // 如果本机没配置过 那么执行一次
$ npm login // 系统将弹出输入用户名以及密码的提示
Username: admin // 取决与你填写在配置文件中的users字段
Password: 我想要的密码 // 仅用于事例,实际不展示密码 密码为配置文件中password字段加密前的明文
登录成功后 你就拥有推送包到私有仓库的权限了
总结
搭建私有仓库其实并非重头,如何考虑、设计通用优雅的私有包才是重中之重。
编者在开发包的过程中,考虑了大量开发中遇到的问题。最终的方案为使用Typescript开发各个包并编写大量@types文件来提升开发体验。如果有机会,可以再聊聊相关的话题。