使用cnpmjs.org搭建私有npm源

前言

淘宝NPM 让很多技术同学过上了爽快的日子,因为访问npmjs.com有时候真的很慢很慢,真的感叹阿里的财大气粗。而且cnpm还开源了,网址为cnpm/cnpmjs.org 。很多公司使用cnpmjs.org搭建了自己的私有npm源,如美团。也包括okcoin。下面简要的写一下步骤。

正题

首先要选择版本,选择的是2.19.4,是最新的稳定版。从tag来看alpha发到alpha 15版本,beta没发,但是npm上的最新版本的tag确实beta1,这里实在没明白。

cnpmjs需要数据库支持,我们选择MariaDB,安装什么的不说,现在假设已经有一台MySQL可用。

我们选择下载源码部署,把代码clone到本地,并从tag 2.19.4创建一个分支。

修改配置是重点, 所有默认配置在config/index.js中,需要创建config/config.js文件来写自己的自定义配置。为啥这样干?因为config/index.js中这样写的。config/index.js中所有配置项都有注释说明,很好懂,把自己要修改的在config/config.js中配置一下即可,比如database

1
2
3
4
5
6
7
8
9
10
11
12
database: {
db: 'cnpm',
username: 'cnpm',
password: 'cnpm_this_is_cnpm_pwd',

// the sql dialect of the database
// - currently supported: 'mysql', 'sqlite', 'postgres', 'mariadb'
dialect: 'mysql',

// custom host; default: 127.0.0.1
host: '192.168.10.36'
},

其他的scopes、npmClient(这个直接决定了在web站点显示的npm client)、registryHost等等。

想接自己公司内部的账号系统需要参照services/default_user_service.js的接口来实现一个UserService,之后配置到config/config.js中,如userService: new UserService() 。

遇到的问题

搭建起来之后发现可以发布npm模块到新搭建的私有源,但是不能安装。以为是自己配置错了,仔细查看配置后发现了没啥问题。所以打断点调试,发现在lib/common.js中发现了如下的一段代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
exports.getCDNKey = function (name, filename) {
// if name is scope package name, need to auto fix filename as a scope package file name
// e.g.: @scope/foo, filename: foo-1.0.0.tgz => filename: @scope/foo-1.0.0.tgz
if (name[0] === '@' && filename[0] !== '@') {
filename = name.split('/')[0] + '/' + filename;
}
return '/' + name + '/-/' + filename;
};
exports.setDownloadURL = function (pkg, ctx, host) {
if (pkg.dist) {
host = host || config.registryHost || ctx.host;
pkg.dist.tarball = util.format('%s://%s/%s/download/%s-%s.tgz',
ctx.protocol,
host, pkg.name, pkg.name, pkg.version);
}
};

第一个方法在发布模块的时候调用到,第二个方法在安装的时候调用到。可以看出生成的url不是一个模式,所以做了修改,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
exports.getCDNKey = function (name, filename) {
// if name is scope package name, need to auto fix filename as a scope package file name
// e.g.: @scope/foo, filename: foo-1.0.0.tgz => filename: @scope/foo-1.0.0.tgz
if (name[0] === '@' && filename[0] !== '@') {
filename = name.split('/')[0] + '/' + filename;
}
return '/' + name + '/-/' + filename;
};
exports.setDownloadURL = function (pkg, ctx, host) {
if (pkg.dist) {
host = host || config.registryHost || ctx.host;
pkg.dist.tarball = util.format('%s://%s:%s/%s/-/%s-%s.tgz',
ctx.protocol,
host, config.registryPort, pkg.name, pkg.name, pkg.version);
}
};

修改主要在第二个方法,在链接中加了registryPort,将download改为- ,这样就成功了。原因应该是财大气粗的都用了云存储,我们在本地机器存储,他们遇不到,我们遇到了。

定制npm client端

阿里内网有自己的tnpm,真的不错,如果想定制一个自己的npm client端也是很容易的,可以直接clone cnpm这个阿里的开源项目之后把npm使用的地址改为自己公司搭建的源即可。哦, 对了,还得在package.json中将bin段的名字改一下,比如叫 mpnpm,也要定制下模块名字。修改完成后发布即可。使用方法

1
2
3
4
5
6
7
$ mpnpm adduser 

$ mpnpm owner add

$ mpnpm i --save

$ mpnpm publish

推荐文章