构建前端团队的私有npm仓库

34 篇文章 0 订阅
14 篇文章 0 订阅

有一点规模的团队,都需要逐渐构建自己的npm包。现在有一个比较好的解决方案Sinopia,可以快速搭建和部署私有的npm服务器。

本文详细记录了我在搭建私有npm包时,遇到的问题,以及个人的思考。

1. 安装Sinopia

安装

首先,你要自己配置nodejs及npm的环境,然后运行

npm install -g sinopia

启动

$ sinopia
 warn  --- config file  - .....\AppData\Roaming\sinopia\config.yaml
 warn  --- http address - http://localhost:4873/

然后打开:http://localhost:4873/

连接中的文档已经写的很详细了,我就不重复造轮子了。

安装Sinopia

深坑预警

后来我们把私有仓库改为了verdaccio,因为sinoipa不支持包命名空间,详情请见下文。

3、搭建好私有npm仓库后遇到什么坑?

我发现使用nrm切换到私有npm仓库对应的源后,下载带@ 符号的包都下载失败,比如下载 @angular/core,就会下载失败,这是为什么呢,查阅了一些资料,发现这其实是Sinopia自己的bug,bug产生的原因就是:sinopia在代理到npmjs.org公有库时将@符号转码为%40,致使在公有库中找不到对应的包,返回404 ,简单点说就是 @angular/core 代理请求的时候被转换成了 %40angular/core,所以我们需要在代理请求发出之前将其转回 @angular/core

4、如何解决?

修改sinopia源码:修改位于sinopia/lib/up-storage.js文件第10行:将var encode = encodeURIComponen;,更改为:var encode = function(thing) {return encodeURIComponent(thing).replace(/^%40/, ‘@’);}; ,这段代码的含义就是将%40转回@,于是就解决了不能下载带有@符号的npm包的bug

5、更好的解决方案?

由于sinopia的作者已于二年前停止对sinopia的维护和升级,所以出来了一个sinopia的fork,名字叫做Verdaccio,然后由Verdaccio继续对sinopia进行更新和维护,具体如何使用Verdaccio来构建私有npm服务器,请见Verdaccio的github介绍

参考文档

2. 构建过程中遇到的问题:

2.1. 外网无法访问私有sinopia服务器
[root@webteam sysconfig]# systemctl stop firewalld.service 
[root@webteam sysconfig]# systemctl start firewalld.service 
[root@webteam sysconfig]# firewall-cmd --permanent --add-port=4873/tcp  
success
[root@webteam sysconfig]# firewall-cmd --reload
success
[root@webteam sysconfig]# 

参考文档

2.2. 开机自启动
ascs@webteam sinopia]$ pm2 save
[PM2] Saving current process list...
[PM2] Successfully saved in /home/ascs/.pm2/dump.pm2
[ascs@webteam .pm2]$ pm2 startup centos
[PM2] Init System found: systemd
-----------------------------------------------------------
 PM2 detected systemd but you precised centos
 Please verify that your choice is indeed your init system
 If you arent sure, just run : pm2 startup
-----------------------------------------------------------
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup centos -u ascs --hp /home/ascs
[ascs@webteam .pm2]$ sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup centos -u ascs --hp /home/ascs

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for ascs: 

2.3. 关于添加用户失败的问题

$ npm adduser
Username: webteam
Password:
Email: (this IS public) (yueshenghu@ascs.tech)
npm ERR! code E500
npm ERR! Internal Server Error

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2018-05-08T13_17_14_767Z-debug.log

这个问题,在查看sinopia服务器之后,我发现是Linux目录权限问题。

[ascs@webteam sinopia]$ sinopia
 warn  --- config file  - /usr/share/nginx/html/sinopia/config.yaml
 warn  --- http address - http://0.0.0.0:4873/
 error --- unexpected error: EACCES: permission denied, open '/usr/share/nginx/html/sinopia/htpasswd'
Error: EACCES: permission denied, open '/usr/share/nginx/html/sinopia/htpasswd'
    at Error (native)
 http  <-- 500, user: undefined, req: 'PUT /-/user/org.couchdb.user:webteam', error: internal server error
 error --- unexpected error: EACCES: permission denied, open '/usr/share/nginx/html/sinopia/htpasswd'
Error: EACCES: permission denied, open '/usr/share/nginx/html/sinopia/htpasswd'
    at Error (native)
 http  <-- 500, user: undefined, req: 'PUT /-/user/org.couchdb.user:webteam', error: internal server error
^C

那么怎么解决这个问题呢?

仔细查看Linux提示的错误,考虑远程向sinopia服务添加用户的时候,也是向linux目录下写文件的时候,这个时候的文件夹,如果没有其他用户的写权限,那么是没有办法写入的。所以就会报错。

解决方法:

进入sinopia的父级目录,然后将sinopia目录的权限提升。

[ascs@webteam sinopia]$ cd ..
[ascs@webteam html]$ su
密码:
[root@webteam html]# chmod 757 sinopia/
[root@webteam html]# ls -al
总用量 20
drwxrwxr-x+ 19 root root 4096 58 14:17 .
drwxr-xr-x.  3 root root   18 43 14:22 ..
-rw-rwxr--+  1 root root  537 53 16:40 50x.html
drwxr-xrwx   3 root root   40 54 19:57 sinopia
2.4. 关于发布包失败的问题

解决了添加用户失败的问题,结果发布包又出了问题,为什么呢?

$ npm publish
npm ERR! Unexpected token u in JSON at position 0

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2018-05-08T13_41_42_751Z-debug.log

查看sinopia的日志

/home/ascs/.pm2/logs/sinopia-error-1.log last 15 lines:
1|sinopia  | Error: EACCES: permission denied, open '/usr/share/nginx/html/sinopia/storage/.sinopia-db.json'
1|sinopia  |     at Error (native)
1|sinopia  |     at Object.fs.openSync (fs.js:642:18)
1|sinopia  |     at Object.fs.writeFileSync (fs.js:1348:33)
1|sinopia  |     at LocalData.sync (/usr/lib/node_modules/sinopia/lib/local-data.js:42:6)
1|sinopia  |     at LocalData.add (/usr/lib/node_modules/sinopia/lib/local-data.js:20:10)
1|sinopia  |     at updater (/usr/lib/node_modules/sinopia/lib/local-storage.js:251:27)
1|sinopia  |     at /usr/lib/node_modules/sinopia/lib/local-storage.js:582:5
1|sinopia  |     at /usr/lib/node_modules/sinopia/lib/local-fs.js:248:8
1|sinopia  |     at callback (/usr/lib/node_modules/sinopia/lib/local-fs.js:197:19)
1|sinopia  |     at onRead (/usr/lib/node_modules/sinopia/lib/local-fs.js:214:9)

没错,又碰上了权限问题。老办法,给.sinopia-db.json添加些权限。

切换到root权限,然后给文件授权。

简单粗暴的给了777,看官如果你要部署在公网上,请慎重哟。

[root@webteam storage]# chmod 777 .sinopia-db.json 
[root@webteam storage]# 
[root@webteam storage]# ls -al
总用量 4
drwxrwxrwx 3 root root  52 5月   8 21:55 .
drwxr-xrwx 3 root root  56 5月   8 21:37 ..
drwxrwxr-x 2 ascs ascs  90 5月   8 21:55 cityworks3d_cm
-rwxrwxrwx 1 root root 103 5月   8 21:55 .sinopia-db.json

再次发布,成功!

$ npm publish
+ cityworks3d_cm@1.0.0

3. 随之而来的问题:

3.1. npm的命名空间问题

如果因为你起的包名与现有的包名太相近而被阻止发布这个包,那么找到一个独一无二包名最简单方法就是使用你的作用域。你可以使用@+你的npm用户名加在包名前面将包划到你的npm账户作用域下。比如,我的npm用户名是ceejbot,所以我的作用域是@ceejbot。

在你自己的作用域下发布一个包是免费的!你可以这样去做:

我已经知道json-stream与现有包名太接近了,所以我需要找到一个新的名字。首先,我需要编辑我的package.json文件,添加我的npm账户名来划分一个作用域,所以:

{
    "name": "json-stream"
}

修改为:

{
    "name": "@ceejbot/json-stream"
}

然后我要发布这个包。被划了作用域的包默认是私有的,所以要通过—access=public 让它变为公有的包:

> npm publish --access=public
+ @ceejbot/json-stream@1.0.0

每个人都可以向npm注册表中发布公共的作用域包,但是你想发布私有的包就要付费订阅了。

参考文章

3.2. 生产环境中的使用

3.2.1. 容器部署

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

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

3.2.2. 版本控制

将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版本一致
邮件通知各组成员 库版本更新信息
3.2.3. 团队使用

团队所有成员切换npm至私有库

推荐使用nrm库 可以方便的切换npm源

nrm add private http://localhost:4873 # 添加源管理

nrm ls # 查看源列表

nrm use private # 切换至该源

npm install @scope/package-name@version --save-dev #

其它操作与npm公用库相同

参考文章

4. 补充说明

4.1. NRM常用命令
nrm最常有的命令有 : 
1.nrm ls 查看已有的源 
2.nrm add <源名称> <源地址> 新增源 
3.nrm use <源名称>切换到现有的源
4.nrm test  测速
4.2. 使用npm安装包

使用 npm –save 标志下载一个包


常规: npm install pkg, 快捷方式: npm i pkg.

常规: npm i --global pkg, 快捷方式: npm i -g pkg.(全局安装一个包)

常规: npm i --save pkg, 快捷方式: npm i -S pkg`.(安装一个项目依赖包,写进dependence)

常规: npm i --save-dev pkg, 快捷方式: npm i -D pkg`.(全局安装一个项目开发依赖包,写进devDependence)

举个栗子:

npm install lodash --save

这将会在下载包文件之前修改 package.json 文件的依赖关系字段。现在打开刚才创建的 package.json 文件我们会发现多了个 dependencies 字段。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值