欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

nrm的使用与源码分析

程序员文章站 2022-07-02 23:24:15
...
一、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发布包–所遇到的问题

相关标签: npm