为什么需要私有npm
官方的 npm 可以说是最大的 JavaScript 模块仓库,大约有 60 多万个开源的 JavaScript 模块。那为什么我们还需要一个私有 npm 仓库呢?
总结起来,有以下几点原因:
保证 npm 服务的快速、稳定。由于国内网络环境的原因,从官方 npm 上安装模块依赖时,可能需要花费很长的时间。在部署私有 npm 后,可以把经过审核的 npm 模块加入到私有仓库,这样在开发环境和生产环境中就可以对模块进行快速安装了。另外还能避免类似 left-pad 事件的发生1。
发布私有 npm 模块。官方 npm 上的模块全部是开源的,然而在实际开发过程中,我们需
方案
sinopia
参考文档:
verdaccio
参考文档:
https://github.com/verdaccio/verdaccio
https://blog.csdn.net/YYZZHC999/article/details/80097073
cnpmjs
参考文档:
https://github.com/cnpm/cnpmjs.org
issues
最终选择的是cnpmjs,因为sinopia虽然有web权限控制,但是其项目本身截至(2018-7-16 18:2:29)有三年未有更新;verdaccio是sinopia的fork.
cnpm简介
CNPM 是一个Nodejs的库,致力于打造私有的 NPM 注册服务。当然,除了私有库功能以外,CNPM官网 (http://cnpmjs.org/) 还提供了NPM同步的服务。
CNPM官方发布的架构图:
从CNPM的架构图中,我们可以看出CNPM是对NPM做的镜像服务,CNPM会定期同步NPM的资源库,同时CNPM支持发布私有的库,这样就非常方便地集成了公有库和私有库,对于公司内部的开发者来说,基本感觉不到两种库的区别。
另外,我们使用NPM下载依赖包时,经常性地会遇到一些包下载失败的情况,主要原因了NPM的注册服务器在国外,国内的网络环境访问国外的IP并不是太好。所以,直接配置到国内的NPM镜像,可以减少NPM下载出错机会。
安装
最低要求
- NodeJS >= 4.3.1
- Databases: only required one type
- sqlite3 >= 3.0.2, we use sqlite3 by default
- MySQL >= 0.5.0, include mysqld and mysql cli. I test on mysql@5.6 and 5.7
- MariaDB
- PostgreSQL
- Python 2.7
- 磁盘尽量大
MySQL
## 这里没有优化参数,大并发的需求,因此不选择用编译安装 ## 以ubuntu为例 $ cd /usr/local/src $ wget https://repo.mysql.com//mysql-apt-config_0.8.10-1_all.deb $ apt-get update $ apt-get install mysql-server
NodeJS
$ cd /usr/local/src $ wget https://nodejs.org/dist/v8.11.3/node-v8.11.3-linux-x64.tar.xz $ tar xf node-v8.11.3-linux-x64.tar.xz $ mv node-v8.11.3-linux-x64 /usr/local $ ln -s /usr/local/node-v8.11.3-linux-x64 /usr/local/node $ ln -s /usr/local/node/bin/npm /usr/local/bin/npm $ ln -s /usr/local/node/bin/node /usr/local/bin/node $ ln -s /usr/local/node/bin/npx /usr/local/bin/npx
代码拉取
$ apt-get install python sqlite3 $ mkdir -p /data/wwwroot && cd /data/wwwroot $ git clone https://github.com/cnpm/cnpmjs.org.git $ cd cnpmjs.org ## 最新的(2018-7-16 17:54:37)3.x不稳定,建议暂时用2.x $ git checkout remotes/origin/2.x $ git branch $ sudo npm install ## 可选: 国内下载如果过慢,开源指定源下载 $ sudo npm install --registry=https://registry.npm.taobao.org ## 可选: 如果用root用户直接运行npm install,那么需要加入--unsafe-perm参数) $ npm install --registry=https://registry.npm.taobao.org --unsafe-perm
MySQL创建数据库和数据库权限
## 新建数据库名 mysql> CREATE DATABASE IF NOT EXISTS cnpmjs_dev DEFAULT CHARSET utf8 COLLATE utf8_general_ci; ## 新建用户 mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, CREATE VIEW, SHOW VIEW ON cnpmjs_dev.* TO 'cnpmjs_root'@'192.168.%.%' IDENTIFIED BY 'conDH55ds9n1p11DH55d'; mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, CREATE VIEW, SHOW VIEW ON cnpmjs_dev.* TO 'cnpmjs_root'@'localhost' IDENTIFIED BY 'conDH55ds9n1p11DH55d'; mysql> flush privileges; ## 导入建表文件 mysql> source /data/wwwroot/cnpmjs.org/docs/db.sql;
当前使用的配置文件(有删改)
... var dataDir = path.join('/data/download/.cnpmjs.org'); ... registryPort: 7001, webPort: 7002, bindingHost:'192.168.99.131', // only binding on 127.0.0.1 for local access ... // enable gzip response or not // enableCompress:是否开启gzip压缩支持,推荐为true enableCompress: true, // default system admins admins: { // name: email ccqq: '1314@qq.com', fengmk2: 'fengmk2@gmail.com', admin: 'admin@cnpmjs.org', dead_horse: 'dead_horse@qq.com', }, ... database: { db: 'cnpmjs_dev', username: 'cnpmjs_root', password: 'conDH55ds9n1p11DH55d', // the sql dialect of the database // - currently supported: 'mysql', 'sqlite', 'postgres', 'mariadb' dialect: 'mysql', // custom host; default: 127.0.0.1 host: '127.0.0.1', // custom port; default: 3306 port: 3306, sessionSecret: '37376.com cnpmjs.org session secret', ... // enable private mode or not // private mode: only admins can publish, other users just can sync package from source npm // public mode: all users can publish // “none”:永不同步,只管理私有用户上传的包,其他源包会直接从源站获取; // “exist”:定时同步已经存在于数据库的包; // “all”:定时同步所有源站的包; enablePrivate: true, // registry scopes, if don't set, means do not support scopes //也就是在 install 的时候遇到含有 scope 的包就会去私有npm下载包 如:@cnpm/demo ,公共的 npm 会去 sourceNpmRegistry: 'https://registry.npm.taobao.org', 下载包 。 // scopes: [ '@cnpm', '@cnpmtest', '@cnpm-test' ], scopes: [ '@cnpm', '@cnpmtest', '@cnpm-test', '@37376test', '@37376demo', '@37376' ], ... // upstream registry is base on cnpm/cnpmjs.org or not // if your upstream is official npm registry, please turn it off sourceNpmRegistryIsCNpm: true, // if install return 404, try to sync from source registry syncByInstall: true, // sync mode select // none: do not sync any module, proxy all public modules from sourceNpmRegistry // exist: only sync exist modules // all: sync all modules syncModel: 'exist', // 'none', 'all', 'exist' ... // sync devDependencies or not, default is false syncDevDependencies: true, // try to remove all deleted versions from original registry syncDeletedVersions: true, ... };
启动
$ node start or $ nohup node /data/wwwroot/cnpmjs.org/dispatch.js > /data/download/.cnpmjs.org/logs/nodejs_stdout.log 2>&1 &
使用cnpm
下载
如果私有库没有对应的库,cnpm会自动同步到NPM 找到我们要下载的库和版本,先在CNPM中存一份,然后再传给客户端一份,运行原理和Maven的原理一样。
$ npm install request --registry=http://192.168.99.131:7001
上传
默认cnpm只有admin组才有权限上传。
# make sure you have login cnpm
$ cnpm publish