一、解决 This is probably not a problem with npm. There is likely additional logging output above

  在执行 npm run serve 运行项目的时候报错:



npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! lianshan@2.0.0 serve: `vue-cli-service serve`
npm ERR! Exit status 1
npm ERR!
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /Users/.../_logs/..._10_01_084Z-debug.log


  如果出现这种报错情况,一般需要重新安装 node_modules 文件夹中的内容,但是在安装前,要把之前的内容都清空掉。

  其实大多数的主要问题是 package-lock.json 这个文件,一般使用 1、2、4 步就够了,如果不行在重新 1、2、3、4 步,因为使用了 第3步,在 $ npm install 安装会要点时间,相对较慢。

  解决步骤如下:

1、首先删除 node_modules,可以命令行删除,也可以手动右键删除文件夹。

2、删除 package-lock.json 文件

3、运行命令



npm cache clean --force


4、重新安装依赖:npm install

二、npm模块安装机制

1、npm install 安装之前,​​npm install​​会先检查​​node_modules​​目录之中是否已经存在指定模块。如果存在,就不再重新安装了,即使远程仓库已经有了一个新版本,也是如此。

  如果你希望,一个模块不管是否安装过,npm 都要强制重新安装,可以使用​​-f​​或​​--force​​参数。



npm install <packageName> --force


2、如果想更新已安装模块,就要用到​​npm update​​命令。



npm update <packageName>


  它会先到远程仓库查询最新版本,然后查询本地版本。如果本地版本不存在,或者远程版本较新,就会安装。

3、​​那么npm update​​命令怎么知道每个模块的最新版本呢?

  答案是 npm 模块仓库提供了一个查询服务,叫做 registry 。以 npmjs.org 为例,它的查询服务网址是 ​​https://registry.npmjs.org/​​ 。

  这个网址后面跟上模块名,就会得到一个 JSON 对象,里面是该模块所有版本的信息。比如,访问 ​​https://registry.npmjs.org/react​​,就会看到 react 模块所有版本的信息。

  它跟下面命令的效果是一样的。



npm view react

// npm view 的别名
npm info react
npm show react
npm v react


  registry 网址的模块名后面,还可以跟上版本号或者标签,用来查询某个具体版本的信息。比如, 访问 https://registry.npmjs.org/react/v0.14.6 ,就可以看到 React 的 0.14.6 版。

  返回的 JSON 对象里面,有一个​​dist.tarball​​属性,是该版本压缩包的网址。



dist: {
shasum: '2a57c2cf8747b483759ad8de0fa47fb0c5cf5c6a',
tarball: 'http://registry.npmjs.org/react/-/react-0.14.6.tgz'
},


  到这个网址下载压缩包,在本地解压,就得到了模块的源码。​​npm install​​和​​npm update​​命令,都是通过这种方式安装模块的。

4、缓存目录

​  npm install​​或​​npm update​​命令,从 registry 下载压缩包之后,都存放在本地的缓存目录。

  这个缓存目录,在 Linux 或 Mac 默认是用户主目录下的​​.npm​​目录,在 Windows 默认是​​%AppData%/npm-cache​​。通过配置命令,可以查看这个目录的具体位置。



PS D:\modb-front\modb-front> npm config get cache
D:\Program\nodejs\node_cache


  浏览一下这个目录,会看到里面存放着大量的模块,储存结构是​​{cache}/{name}/{version}​



npm cache ls react

~/.npm/react/react/0.14.6/
~/.npm/react/react/0.14.6/package.tgz
~/.npm/react/react/0.14.6/package/
~/.npm/react/react/0.14.6/package/package.json


  每个模块的每个版本都有一个自己的子目录,里面是代码的压缩包​​package.tgz​​文件,以及一个描述文件​​package/package.json​​。

  除此之外,还会生成一个​​{cache}/{hostname}/{path}/.cache.json​​文件。比如,从 npm 官方仓库下载 react 模块的时候,就会生成​​registry.npmjs.org/react/.cache.json​​文件。

  这个文件保存的是,所有版本的信息,以及该模块最近修改的时间和最新一次请求时服务器返回的 ETag 。



{
"time":{
"modified":"2016-01-06T23:52:45.571Z",
// ...
},
"_etag":"\"7S37I0775YLURCFIO8N85FO0F\""
}


  对于一些不是很关键的操作(比如​​npm search​​或​​npm view​​),npm会先查看​​.cache.json​​里面的模块最近更新时间跟当前时间的差距,是不是在可接受的范围之内。如果是的,就不再向远程仓库发出请求,而是直接返回​​.cache.json​​的数据。

5、模块的安装过程

  Node模块的安装过程是这样的:

1、发出​​npm install​​命令

2、npm 向 registry 查询模块压缩包的网址

3、下载压缩包,存放在​​~/.npm​​目录

4、解压压缩包到当前项目的​​node_modules​​目录

  注意,一个模块安装以后,本地其实保存了两份。一份是​​~/.npm​​目录下的压缩包,另一份是​​node_modules​​目录下解压后的代码。

  但是,运行​​npm install​​的时候,只会检查​​node_modules​​目录,而不会检查​​~/.npm​​目录。也就是说,如果一个模块在​​~/.npm​​下有压缩包,但是没有安装在​​node_modules​​目录中,npm 依然会从远程仓库下载一次新的压缩包。

  这种行为固然可以保证总是取得最新的代码,但有时并不是我们想要的。最大的问题是,它会极大地影响安装速度。即使某个模块的压缩包就在缓存目录中,也要去远程仓库下载,这怎么可能不慢呢?

  另外,有些场合没有网络(比如飞机上),但是你想安装的模块,明明就在缓存目录之中,这时也无法安装。

6、​​--cache-min​​ 参数

  为了解决这些问题,npm 提供了一个​​--cache-min​​参数,用于从缓存目录安装模块。

​  --cache-min​​参数指定一个时间(单位为分钟),只有超过这个时间的模块,才会从 registry 下载。



npm install --cache-min 9999999 <package-name>


  上面命令指定,只有超过999999分钟的模块,才从 registry 下载。实际上就是指定,所有模块都从缓存安装,这样就大大加快了下载速度。