关于局部安装npm模块找不到命令的问题分析及解决方案

时间:2022-06-06 17:41:44

通常情况下我们使用npm进行模块安装时分为全局安装和局部安装两种模式,在测试情况下一般喜欢用全局安装方式,而开发环境中则常常使用局部安装,这样做既是为了不对系统环境产生过多依赖,也有助于模块的关系解耦以及提高项目的可移植性。但是使用过局部安装的朋友们可能都遇见过“xxx不是内部或外部命令”等这样的提示,明明全局安装下直接打出命令就可以执行,为何局部安装就不可以呢?

这里其实是一个很大的坑,笔者初次遇见这个问题时也被困扰了很久,原因在于我们并不了解windows系统下命令的执行原理以及node模块的内置命令的启动方式,接下来我们就探究一下其内部机制以及解决方案,让大家少走一些弯路~。

我们来实际操作一下,拿我当时新建一个项目node-server举例,配置好基本项后,假设我们需要安装babel-cli转码工具,首先尝试采用全局安装,就是:

npm install babel-cli -g   

安装后会发现项目路径下没有多余的文件,那么模块被安装到哪里了呢?实际上被安装到了系统盘下管理用户数据文件夹中的npm文件夹内,内部包含的都是全局按装过的npm模块,比如我的电脑路径就是:

关于局部安装npm模块找不到命令的问题分析及解决方案

可以看到这里存放了大量的模块,grunt、webpack、nw等工具,当你在系统任意路径下直接运行这几个命令时,就会自动查找到这个路径下,然后执行里面的代码。

那么接下来,如果是局部安装呢?我们首先将全局的模块删除掉(为了排除干扰),然后命令行切到项目根目录下,输出:

npm install --save-dev babel-cli

这时我们会发现项目根目录下多了个node_modules文件夹,你会发现内部包含有若干文件模块:

关于局部安装npm模块找不到命令的问题分析及解决方案

这里便是我们要的babel模块,也就是说在项目下面运行babel index.js这样的命令的话,应该输出转码后的js代码。我们给根目录下的index.js文件写入如下代码然后执行命令:

import http from 'http'

但这里我们直接输出会发现命令行报错提示找不到命令:

关于局部安装npm模块找不到命令的问题分析及解决方案

这是为什么呢?这里就涉及到windows下执行npm命令的实质。假设全局安装模式下,我们使用babel命令,系统会默认找到上面发的那个c盘的目录下,我们重点看一下npm文件夹里面的内容:

关于局部安装npm模块找不到命令的问题分析及解决方案

会发现这里面有很多cmd文件,这些其实就是windows下的命令脚本文件,也就是假设你输入babel命令,系统会默认找到这里来寻找babel.cmd文件,如果有就执行,如果没有就报错命令找不到。

所以回到我们都项目中,刚刚使用了局部安装而全局中c盘这个目录下根本没有babel.cmd这个文件,那我们该怎么办呢?

其实细心的人如果打开项目局部安装目录下的文件夹,就会发现里面有个.bin文件夹,其实这个里面保存的就是各个node模块的二进制命令脚本文件,babel的文件当然也在此处:

关于局部安装npm模块找不到命令的问题分析及解决方案

关于局部安装npm模块找不到命令的问题分析及解决方案

关于局部安装npm模块找不到命令的问题分析及解决方案

终于,我们找到了命令行的源头。接下来解决问题就很简单了,我们这次如果想实现命令行转码,只需要在命令前面加上具体的路径就可以了,比如刚才的就应该改成:

node_modules\.bin\babel index.js

这样我们得到的结果:

关于局部安装npm模块找不到命令的问题分析及解决方案

问题终于得到了解决,但是每次需要手动输入确实很麻烦。

简化的办法有两种:

一种是把命令脚本文件复制到c盘响应的文件夹下面,但是不建议采用这种方式,因为依然对系统产生了依赖,这样就和全局安装没有区别了;

第二种方式就是在packjson文件里面配置scripts项,相当于将命令行语句保存下来,之后只要运行简单的命令类似:npm run build,就可以实现了。

(这里的原理:package.json中的script会按照一定顺序寻找命令对应位置,本地的node_modules\.bin路径就在这个寻找清单中,所以无论是全局还是局部安装的,你都不需要写前面那指明详细的路径了。注意:npm的start命令是一个特殊的脚本名称,其特殊性表现在,在命令行中使用npm start就可以执行其对于的命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}如npm run build

package.json文件配置如下:

关于局部安装npm模块找不到命令的问题分析及解决方案

最终我们在命令行得到:

关于局部安装npm模块找不到命令的问题分析及解决方案

有错误的地方还望大家纠正~