nrm的使用与源码分析
程序员文章站
2022-07-02 23:24:15
...
一、nrm的使用
.在使用npm进行项目拉取的时候,我们可能会进行切换不同的镜像去下载,下面这个就是快速切换镜像的插件
快速切换npm源的开源工具nrm-github地址
快速切换npm源的开源工具–nrm
在这里我们对nrm源码进行查看:
1.如下所示,nrm源码结构
在上面源码中,各个文件对应意义如下所示:
.gitignore--------------------git上传文件时的忽略文件
cli.js------------------------nrm项目的主要代码
package.json------------------npm项目配置文件
registries.json---------------已经注册过的镜像地址,可以进行拉取包的镜像
2.cli.js文件说明
首先来看一下代码内容
#!/usr/bin/env node
var path = require('path');
var fs = require('fs');
var program = require('commander');
var npm = require('npm');
var ini = require('ini');
var echo = require('node-echo');
var extend = require('extend');
var open = require('open');
var async = require('async');
var request = require('request');
var only = require('only');
var registries = require('./registries.json');
var PKG = require('./package.json');
var NRMRC = path.join(process.env.HOME, '.nrmrc');
program
.version(PKG.version);
program
.command('ls')
.description('List all the registries')
.action(onList);
program
.command('current')
.description('Show current registry name')
.action(showCurrent);
program
.command('use <registry>')
.description('Change registry to registry')
.action(onUse);
program
.command('add <registry> <url> [home]')
.description('Add one custom registry')
.action(onAdd);
program
.command('del <registry>')
.description('Delete one custom registry')
.action(onDel);
program
.command('home <registry> [browser]')
.description('Open the homepage of registry with optional browser')
.action(onHome);
program
.command('test [registry]')
.description('Show response time for specific or all registries')
.action(onTest);
program
.command('help')
.description('Print this help')
.action(function () {
program.outputHelp();
});
program
.parse(process.argv);
if (process.argv.length === 2) {
program.outputHelp();
}
/*//////////////// cmd methods /////////////////*/
function onList() {
getCurrentRegistry(function(cur) {
var info = [''];
var allRegistries = getAllRegistry();
Object.keys(allRegistries).forEach(function(key) {
var item = allRegistries[key];
var prefix = item.registry === cur ? '* ' : ' ';
info.push(prefix + key + line(key, 8) + item.registry);
});
info.push('');
printMsg(info);
});
}
function showCurrent() {
getCurrentRegistry(function(cur) {
var allRegistries = getAllRegistry();
Object.keys(allRegistries).forEach(function(key) {
var item = allRegistries[key];
if (item.registry === cur) {
printMsg([key]);
return;
}
});
});
}
function onUse(name) {
var allRegistries = getAllRegistry();
if (allRegistries.hasOwnProperty(name)) {
var registry = allRegistries[name];
npm.load(function (err) {
if (err) return exit(err);
npm.commands.config(['set', 'registry', registry.registry], function (err, data) {
if (err) return exit(err);
console.log(' ');
var newR = npm.config.get('registry');
printMsg([
'', ' Registry has been set to: ' + newR, ''
]);
})
});
} else {
printMsg([
'', ' Not find registry: ' + name, ''
]);
}
}
function onDel(name) {
var customRegistries = getCustomRegistry();
if (!customRegistries.hasOwnProperty(name)) return;
getCurrentRegistry(function(cur) {
if (cur === customRegistries[name].registry) {
onUse('npm');
}
delete customRegistries[name];
setCustomRegistry(customRegistries, function(err) {
if (err) return exit(err);
printMsg([
'', ' delete registry ' + name + ' success', ''
]);
});
});
}
function onAdd(name, url, home) {
var customRegistries = getCustomRegistry();
if (customRegistries.hasOwnProperty(name)) return;
var config = customRegistries[name] = {};
if (url[url.length - 1] !== '/') url += '/'; // ensure url end with /
config.registry = url;
if (home) {
config.home = home;
}
setCustomRegistry(customRegistries, function(err) {
if (err) return exit(err);
printMsg([
'', ' add registry ' + name + ' success', ''
]);
});
}
function onHome(name, browser) {
var allRegistries = getAllRegistry();
var home = allRegistries[name] && allRegistries[name].home;
if (home) {
var args = [home];
if (browser) args.push(browser);
open.apply(null, args);
}
}
function onTest(registry) {
var allRegistries = getAllRegistry();
var toTest;
if (registry) {
if (!allRegistries.hasOwnProperty(registry)) {
return;
}
toTest = only(allRegistries, registry);
} else {
toTest = allRegistries;
}
async.map(Object.keys(toTest), function(name, cbk) {
var registry = toTest[name];
var start = +new Date();
request(registry.registry + 'pedding', function(error) {
cbk(null, {
name: name,
registry: registry.registry,
time: (+new Date() - start),
error: error ? true : false
});
});
}, function(err, results) {
getCurrentRegistry(function(cur) {
var msg = [''];
results.forEach(function(result) {
var prefix = result.registry === cur ? '* ' : ' ';
var suffix = result.error ? 'Fetch Error' : result.time + 'ms';
msg.push(prefix + result.name + line(result.name, 8) + suffix);
});
msg.push('');
printMsg(msg);
});
});
}
/*//////////////// helper methods /////////////////*/
/*
* get current registry
*/
function getCurrentRegistry(cbk) {
npm.load(function(err, conf) {
if (err) return exit(err);
cbk(npm.config.get('registry'));
});
}
function getCustomRegistry() {
return fs.existsSync(NRMRC) ? ini.parse(fs.readFileSync(NRMRC, 'utf-8')) : {};
}
function setCustomRegistry(config, cbk) {
echo(ini.stringify(config), '>', NRMRC, cbk);
}
function getAllRegistry() {
return extend({}, registries, getCustomRegistry());
}
function printErr(err) {
console.error('an error occured: ' + err);
}
function printMsg(infos) {
infos.forEach(function(info) {
console.log(info);
});
}
/*
* print message & exit
*/
function exit(err) {
printErr(err);
process.exit(1);
}
function line(str, len) {
var line = new Array(Math.max(1, len - str.length)).join('-');
return ' ' + line + ' ';
}
如下代码,进行引入使用的依赖包
#!/usr/bin/env node
var path = require('path');
var fs = require('fs');
var program = require('commander');
var npm = require('npm');
var ini = require('ini');
var echo = require('node-echo');
var extend = require('extend');
var open = require('open');
var async = require('async');
var request = require('request');
var only = require('only');
var registries = require('./registries.json');
var PKG = require('./package.json');
var NRMRC = path.join(process.env.HOME, '.nrmrc');
上面代码中,第一行这种用法是为了防止操作系统用户没有将node装在默认的/usr/bin路径里。当系统看到这一行的时候,首先会到env设置里查找node的安装路径,再调用对应路径下的解释器程序完成操作。
commander包是npm依赖排名前十之一的模块,主要作用为命令行辅助工具
registries注册的npm镜像
PKG是package.json文件,在这里用于获取包的版本号
NRMRC是npm配置文件的位置,用于写入npm配置信息,里边就包含npm镜像的地址位置
如下代码,能够使用的命令行代码
program
.version(PKG.version); //package包的版本
program
.command('ls') //可以输入的命令ls
.description('List all the registries')//描述性信息
.action(onList); //调用该命令行对应的方法
program
.command('current')//可以输入的命令ls
.description('Show current registry name')//描述性信息
.action(showCurrent); //调用的方法名,对应后面自己写的方法名,在该方法中进行该命令行对应的代码功能
program
.command('use <registry>')
.description('Change registry to registry')
.action(onUse);
program
.command('add <registry> <url> [home]')
.description('Add one custom registry')
.action(onAdd);
program
.command('del <registry>')
.description('Delete one custom registry')
.action(onDel);
program
.command('home <registry> [browser]')
.description('Open the homepage of registry with optional browser')
.action(onHome);
program
.command('test [registry]')
.description('Show response time for specific or all registries')
.action(onTest);
program
.command('help')
.description('Print this help')
.action(function () {
program.outputHelp();
});
program
.parse(process.argv);
if (process.argv.length === 2) {
program.outputHelp();
}
命令行调用的方法
/*//////////////// cmd methods /////////////////*/
function onList() {//展示镜像列表的方法,对应上面命令行代码中action调用的方法名
getCurrentRegistry(function(cur) {
var info = [''];
var allRegistries = getAllRegistry();
Object.keys(allRegistries).forEach(function(key) {
var item = allRegistries[key];
var prefix = item.registry === cur ? '* ' : ' ';
info.push(prefix + key + line(key, 8) + item.registry);
});
info.push('');
printMsg(info);
});
}
function showCurrent() {//展示当前使用的镜像
getCurrentRegistry(function(cur) {
var allRegistries = getAllRegistry();
Object.keys(allRegistries).forEach(function(key) {
var item = allRegistries[key];
if (item.registry === cur) {
printMsg([key]);
return;
}
});
});
}
function onUse(name) {
var allRegistries = getAllRegistry();
if (allRegistries.hasOwnProperty(name)) {
var registry = allRegistries[name];
npm.load(function (err) {
if (err) return exit(err);
npm.commands.config(['set', 'registry', registry.registry], function (err, data) {
if (err) return exit(err);
console.log(' ');
var newR = npm.config.get('registry');
printMsg([
'', ' Registry has been set to: ' + newR, ''
]);
})
});
} else {
printMsg([
'', ' Not find registry: ' + name, ''
]);
}
}
function onDel(name) {
var customRegistries = getCustomRegistry();
if (!customRegistries.hasOwnProperty(name)) return;
getCurrentRegistry(function(cur) {
if (cur === customRegistries[name].registry) {
onUse('npm');
}
delete customRegistries[name];
setCustomRegistry(customRegistries, function(err) {
if (err) return exit(err);
printMsg([
'', ' delete registry ' + name + ' success', ''
]);
});
});
}
function onAdd(name, url, home) {
var customRegistries = getCustomRegistry();
if (customRegistries.hasOwnProperty(name)) return;
var config = customRegistries[name] = {};
if (url[url.length - 1] !== '/') url += '/'; // ensure url end with /
config.registry = url;
if (home) {
config.home = home;
}
setCustomRegistry(customRegistries, function(err) {
if (err) return exit(err);
printMsg([
'', ' add registry ' + name + ' success', ''
]);
});
}
function onHome(name, browser) {
var allRegistries = getAllRegistry();
var home = allRegistries[name] && allRegistries[name].home;
if (home) {
var args = [home];
if (browser) args.push(browser);
open.apply(null, args);
}
}
function onTest(registry) {
var allRegistries = getAllRegistry();
var toTest;
if (registry) {
if (!allRegistries.hasOwnProperty(registry)) {
return;
}
toTest = only(allRegistries, registry);
} else {
toTest = allRegistries;
}
async.map(Object.keys(toTest), function(name, cbk) {
var registry = toTest[name];
var start = +new Date();
request(registry.registry + 'pedding', function(error) {
cbk(null, {
name: name,
registry: registry.registry,
time: (+new Date() - start),
error: error ? true : false
});
});
}, function(err, results) {
getCurrentRegistry(function(cur) {
var msg = [''];
results.forEach(function(result) {
var prefix = result.registry === cur ? '* ' : ' ';
var suffix = result.error ? 'Fetch Error' : result.time + 'ms';
msg.push(prefix + result.name + line(result.name, 8) + suffix);
});
msg.push('');
printMsg(msg);
});
});
}
帮助信息方法
/*//////////////// helper methods /////////////////*/
/*
* get current registry
*/
function getCurrentRegistry(cbk) {
npm.load(function(err, conf) {
if (err) return exit(err);
cbk(npm.config.get('registry'));
});
}
function getCustomRegistry() {
return fs.existsSync(NRMRC) ? ini.parse(fs.readFileSync(NRMRC, 'utf-8')) : {};
}
function setCustomRegistry(config, cbk) {
echo(ini.stringify(config), '>', NRMRC, cbk);
}
function getAllRegistry() {
return extend({}, registries, getCustomRegistry());
}
function printErr(err) {
console.error('an error occured: ' + err);
}
function printMsg(infos) {
infos.forEach(function(info) {
console.log(info);
});
}
打印信息语句
/*
* print message & exit
*/
function exit(err) {
printErr(err);
process.exit(1);
}
function line(str, len) {
var line = new Array(Math.max(1, len - str.length)).join('-');
return ' ' + line + ' ';
}
3.registries.json文件说明
在下面这个文件中,指明了镜像的地址,通过在.npmrc中修改该地址,能够进行切换npm镜像地址,下面就是可以拉取包的npm
{
"npm": {
"home": "https://www.npmjs.org",
"registry": "https://registry.npmjs.org/"
},
"cnpm": {
"home": "http://cnpmjs.org",
"registry": "http://r.cnpmjs.org/"
},
"taobao": {
"home": "https://npm.taobao.org",
"registry": "https://registry.npm.taobao.org/"
},
"nj": {
"home": "https://www.nodejitsu.com",
"registry": "https://registry.nodejitsu.com/"
},
"rednpm": {
"home": "http://npm.mirror.cqupt.edu.cn/",
"registry": "http://registry.mirror.cqupt.edu.cn/"
},
"npmMirror": {
"home": "https://skimdb.npmjs.com/",
"registry": "https://skimdb.npmjs.com/registry/"
},
"edunpm": {
"home": "http://www.enpmjs.org",
"registry": "http://registry.enpmjs.org/"
}
}
二、npm包发布问题
推荐阅读
-
Python3.5基础之NumPy模块的使用图文与实例详解
-
使用Python3中的gettext模块翻译Python源码以支持多语言
-
linux下使用crontab实现定时PHP计划任务失败的原因分析
-
使用Nginx反向代理与proxy_cache缓存搭建CDN服务器的配置方法
-
ubuntu中snap包的安装、更新删除与简单使用
-
serv-u服务器的管理方法与功能分析
-
C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)
-
使用Visual Studio的查找与替换替代默认的系统搜索
-
UG钣金模式中的伸直与重新折弯命令怎么使用?
-
LINUX运维实战案例之文件已删除但空间不释放问题的分析与解决办法