生产环境下的私有npm服务构建

sinopia服务

私有npm的优势

  1. 内网服务器安装依赖 妈妈再也不用担心GFW(
  2. 库代码的权限控制
  3. 与其它npm库相同的依赖方式, 减少学习成本. 无需使用gitsubmodule等方式
  4. 通过类似npm官网的网站一目了然公司使用的全部模块/版本

技术方案

sinopia: 搭建私有的npm服务, 它可以做到以下事情

  • 上传/下载私有的npm库
  • proxy机制, 非全量同步,本地未找到依赖自动去指定源下载, 然后缓存至sinopia/storage(可修改)
  • 覆盖公有库, 方便的修改开源项目
  • 自带前端管理网站

pm2: 强大的node.js命令行部署/托管工具

nrm: 方便的切换npm源的CLI工具

安装依赖

1
npm install -g sinopia pm2 nrm

开启sinopia

输入pm2 start sinopia开启服务

访问http://localhost:4873
看到这个页面即为搭建成功

配置sinopia

sinopia的目录位于你第一次执行开启命令的目录

  • storage: 私有库存放地址
  • htpasswd: 用户管理
  • config.yaml: 配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
storage: ./storage  # npm包存放的路径

auth:
htpasswd:
file: ./htpasswd # 保存用户的账号密码等信息
max_users: -1 # 最大允许的用户数量,-1则为禁止注册

uplinks:
npmjs:
url: registry.npm.taobao.org # npm地址 当在本地服务找不到依赖时则会拉取这个源的npm库

packages: # 配置权限管理 所有用户有权限拉取项目 但是没有权限更新项目
'@*/*':
# scoped packages
access: $all
publish: $authenticated

'*':
access: $all
publish: $authenticated
proxy: npmjs

# log settings
logs:
- {type: stdout, format: pretty, level: http}

listen: 0.0.0.0:4873 # 默认没有,只能在本机访问,添加后可以通过外网访问。

生产环境中的使用

容器部署

最佳实践是将sinopia作为单独服务部署在docker容器中

在此我制作了一个可以直接使用的docker image 启动容器则自动开启服务, pm2将会守护sinopia进程

版本控制

将sinopia作为公司内部npm库还存在几个问题

  • 使用npm publish上传的流程无法统一管理, 也就是无法持续集成/code review
  • 每个版本的更新信息完全依靠文档, 无法通过code diff追溯

以gitlab为例, 我的做法是

  • 将ci runner的服务器切换至私有源, 使用npm adduser注册一个root用户
  • 在sinopia服务器上将sinopia/config.yaml中的max-users设置为-1, 禁止注册与私自更新版本
  • 将node库源代码在gitlab中创建项目 提交代码走PR流程
  • ci.yml中, build环境处理lint, unit test, production build等流程,tag环境npm publish提交版本, 保持gitlab与npm版本一致
  • 邮件通知各组成员 库版本更新信息

团队使用

团队所有成员切换npm至私有库
前面提到nrm库 可以方便的切换npm源

1
2
3
4
nrm add private http://localhost:4873 # 添加源管理
nrm ls # 查看源列表
nrm use private # 切换至该源
npm install @scope/package-name@version --save-dev # 其它操作与npm公用库相同