npm中本地安装命令行类型的模块是不注册Path的

首先有必要解释下什么是命令行(Command Line)类型的模块
npm的模块一共分为三类:

  1. 绑定型(Binding):本地模块,C++书写,如node-png
  2. 库型(Library):JS书写,直接使用require('module')这种方式,如Socket.IO-node
  3. 命令行型(Command Line): 以命令行形式使用,如json-command

显而易见,提供命令行形式调用方式的模块就属于命令行型的。那么如何来申明自己的模块以什么命令调用,调用执行代码又如何制定呢?

这里就要说到npm模块的核心文件:package.json,此文件是npm模块的配置信息(npm help json可以获取详细信息)。

其中有一个key就叫“bin”,具体形式为“{ "bin": {"command-name" : "command-file"}}”,意思是申明用户可以直接使用“command-name”这个命令,而输入该命令后就会去执行“command-file”这个文件。
比如json-command这个模块,安装好后就可以看到它的package.json文件中bin配置项为“{"bin" : {"json" : "./bin/json.js"}}”。这就申明了命令行名字为“json”,对应地会去执行“bin目录下的json.js”这个文件。

其次还要解释下npm中安装模块的两种模式:

  1. 全局模式: npm -g install module-name,这种模式模块会被安装在node安装记录的lib所在目录的node_modules文件夹中,全局使用
  2. 本地模式: npm install module-name,这种模式模块只会被安装在当前目录的node_modules文件夹中,非全局使用

理解了什么叫“命令行型的模块”“npm模块的安装模式”之后,再来看看什么叫“npm中本地安装命令行类型的模块是不注册Path的”
这句话的意思是说:比如像json-command这样的命令行类型的模块,如果是“全局安装”,安装成功之后,就可以直接使用“json”的命令了,而如果是本地模式安装,则没法使用“json”命令。只能手动找到执行文件,然后调用./command-file这样调用。很是不爽!

后来仔细想了下,npm这样设计也是有道理的,因为命令行的模块,通过命令行使用,一般也都会认为是全局的,就像压缩文件,合并文件之类的命令,一般是不会随着应用的发布而发布的,都只是开发过程中的中间工具。所以,npm对这种类型的模块只有当全局安装的时候才会可以直接使用命令。

那么,“npm到底是如何实现全局直接使用,而本地就不能使用的呢?”

通过查看npm的源码,稍作调试就能发现其中的奥妙了:

  • 通过npm的package.json配置文件就能知道npm的命令行入口是“bin/npm.js”
  • npm.js有会去调用“模块根目录的npm.js”,并会调用相关的命令,依据来自如下代码:
npm = require("../npm");
npm.load(conf, function (er) {
  if (er) return errorHandler(er)
    npm.commands[npm.command](npm.argv, errorHandler)
})
  • “npm.commands...(npm.argv,errorHandler)”是一行典型的command模式代码,npm.js中的commands对象肯定维护了所有command的列表。依据来自如下代码:
var cmd = require(__dirname+"/lib/"+a+".js")
  • 那么install命令就会去调用“lib/install.js”的install方法,install方法会去做一些模块查询模块依赖关系处理模块下载模块安装等工作,之后会去区分本地模式和全局模式,依据来自如下代码:
var fn = npm.config.get("global") ? installMany : installManyTop
  • 之后会去调用lib/build.js中的build函数,依据来自于如下代码:
npm.commands.build([where], false, true, function (er) {
      return cb_(er, d)
})
  • 然后,再看看build函数的申明中,其第二个参数正是表示模块是否全局安装,依据来自如下代码:
function build (args, global, didPre, didRB, cb) {
  • 最后,global参数被赋予给gtop变量,最后判断是否全局,如果是则注册Path否则直接调用回调函数返回,依据来自如下代码:
if (er || !gtop) return cb(er)
var dest = path.resolve(binRoot, b)
     , src = path.resolve(folder, pkg.bin[b])
     , out = npm.config.get("parseable")
                ? dest + "::" + src + ":BINFILE"
                : dest + " -> " + src

这里很清楚,如果“!gtop”,即本地模式就直接调用cb并返回,否则,就去注册Path,其中“dest->src”会发现很眼熟,通常全局安装好一个命令行模块之后,都会显示这行log。这行代码其实就做了如下这件事情:
将命令执行文件json.js link到node/bin/json命令中
其中node的bin路径命令已经被加入到PATH中了,这样输入json的时候,系统自动去PATH中查找对应的执行文件,这样就能够找到了!


参考文献

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 什么是 NPM npm之于Node,就像pip之于Python,gem之于Ruby,composer之于PHP。 ...
    ihoey阅读 6,203评论 2 36
  • 描述 npm从以下来源获取配置值,按优先级排序: 命令行标记 在命令行上放置--foo bar设置foo配置参数为...
    竹天亮阅读 43,492评论 0 8
  • 1 Node.js安装与配置 1.1 Windows平台下的Node.js安装 在过去,Node.js一直不支持在...
    七寸知架构阅读 3,882评论 0 50
  • 今天一天在卖场的见识,突然让我觉得销售是一件很有挑战并且非常让人有成就感的事情!今天的见识让我深深觉得销售完全是在...
    刘艳芳lyf阅读 199评论 0 0
  • 那些让你难过的事情,有一天,你一定会笑着说出来,那就让往事随风,你别回头也别再将就,唯一能做的就是努力让自己过得好...
    後会无期阅读 187评论 0 0