nrm的使用与源码分析

一、nrm的使用

.在使用npm进行项目拉取的时候,我们可能会进行切换不同的镜像去下载,下面这个就是快速切换镜像的插件
快速切换npm源的开源工具nrm-github地址
快速切换npm源的开源工具–nrm
在这里我们对nrm源码进行查看:
1.如下所示,nrm源码结构
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包发布问题

npm发布包–所遇到的问题

猜你喜欢

转载自blog.csdn.net/suwu150/article/details/79961259
nrm