文档章节

npm 模块安装机制简介

小哥哥
 小哥哥
发布于 2016/01/27 09:02
字数 1896
阅读 483
收藏 3
npm

npm 是 Node 的模块管理器,功能极其强大。它是 Node 获得成功的重要原因之一。

正因为有了npm,我们只要一行命令,就能安装别人写好的模块 。

$ npm install

本文介绍 npm 模块安装机制的细节,以及如何解决安装速度慢的问题。

一、从 npm install 说起

npm install 命令用来安装模块到node_modules目录。

$ npm install <packageName>

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

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

$ npm install <packageName> --force

二、npm update

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

$ npm update <packageName>

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

三、registry

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命令,都是通过这种方式安装模块的。

四、缓存目录

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

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

$ npm config get cache 
$HOME/.npm

你最好浏览一下这个目录。

$ ls ~/.npm 
# 或者 
$ npm cache ls

你会看到里面存放着大量的模块,储存结构是{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的数据。

.npm目录保存着大量文件,清空它的命令如下。

$ rm -rf ~/.npm/* 
# 或者 
$ npm cache clean

五、模块的安装过程

总结一下,Node模块的安装过程是这样的。

  1. 发出npm install命令
  2. npm 向 registry 查询模块压缩包的网址
  3. 下载压缩包,存放在~/.npm目录
  4. 解压压缩包到当前项目的node_modules目录

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

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

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

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

六、--cache-min 参数

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

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

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

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

它还有另一种写法。

$ npm install --cache-min Infinity <package-name>

但是,这并不等于离线模式,这时仍然需要网络连接。因为现在的--cache-min实现有一些问题。

(1)如果指定模块不在缓存目录,那么 npm 会连接 registry,下载最新版本。这没有问题,但是如果指定模块在缓存目录之中,npm 也会连接 registry,发出指定模块的 etag ,服务器返回状态码304,表示不需要重新下载压缩包。

(2)如果某个模块已经在缓存之中,但是版本低于要求,npm会直接报错,而不是去 registry 下载最新版本。

npm 团队知道存在这些问题,正在重写 cache。并且,将来会提供一个--offline参数,使得 npm 可以在离线情况下使用。

不过,这些改进没有日程表。所以,当前使用--cache-min改进安装速度,是有问题的。

七、离线安装的解决方案

社区已经为npm的离线使用,提出了几种解决方案。它们可以大大加快模块安装的速度。

解决方案大致分成三类。

第一类,Registry 代理。

上面三个模块的用法很类似,都是在本机起一个 Registry 服务,所有npm install命令都要通过这个服务代理。

# npm-proxy-cache 
$ npm --proxy http://localhost:8080 \     
--https-proxy http://localhost:8080 \     
--strict-ssl false \
      install
 
# local-npm 
$ npm set registry http://127.0.0.1:5080
 
# npm-lazy 
$ npm --registry http://localhost:8080/ install socket.io

有了本机的Registry服务,就能完全实现缓存安装,可以实现离线使用。

第二类,npm install替代。

如果能够改变npm install的行为,就能实现缓存安装。npm-cache 工具就是这个思路。凡是使用npm install的地方,都可以使用npm-cache替代。

$ npm-cache install

第三类,node_modules作为缓存目录。

这个方案的思路是,不使用.npm缓存,而是使用项目的node_modules目录作为缓存。

上面两个工具,都能将项目的node_modules目录打成一个压缩包,以后安装的时候,就从这个压缩包之中取出文件。

作者: 阮一峰

本文转载自:http://www.ruanyifeng.com/blog/2016/01/npm-install.html

共有 人打赏支持
小哥哥
粉丝 21
博文 14
码字总数 0
作品 0
成都
程序员
私信 提问
npm 模块安装机制简介

npm 是 Node 的模块管理器,功能极其强大。它是 Node 获得成功的重要原因之一。 正因为有了npm,我们只要一行命令,就能安装别人写好的模块 。 本文介绍 npm 模块安装机制的细节,以及如何解...

阮一峰
2016/01/21
0
0
Nodejs和NPM初步认识

一、Nodejs 搭建 关于 Windows下的安装方法见 Windows下安装nodejs及环境配置 Nodejs的网络学习教程 见nodejs和npm使用教程 二、NPM NPM基础 NPM的全称是Node Package Manager,是一个NodeJ...

dhb_oschina
2016/04/20
46
0
手把手教你创建你的第一个 NPM 包

1.npm是什么? npm 是Node 的模块管理器,功能极其强大。 它是Node 获得成功的重要原因之一。 正因为有了npm,我们只要一行命令,就能安装别人写好的模块。 npm的基础知识这边就不做表述的,...

小钱钱阿圣
2017/07/21
0
0
Javascript:npm模块安装机制简介

正因为有了npm,我们只要一行命令,就能安装别人写好的模块 。 1 本文介绍 npm 模块安装机制的细节,以及如何解决安装速度慢的问题。 一、从 说起 npm install 命令用来安装模块到node_modu...

燕儿199606
2018/06/19
0
0
NodeJS模块--EverythingStays

EverythingStays是一个不可变的分布式的NodeJS模块。 简介 至今为止任然有很多的工作者使用 NPM工作。我们应该感激社会让NPM公司走到今天这一步。然而,随着越来越多的用户依赖单点来获取应用...

匿名
2016/03/29
221
0

没有更多内容

加载失败,请刷新页面

加载更多

Android安全防护防护———加密算法

摘要 这篇文章本来早就应该写了,但是由于项目一直开发新的需求,就拖后了。现在有时间了,必须得写了。现在Android应用程序对安全防范这方面要求越来越高了。特别是金融行业,如果金融app没...

北辰丨丶
31分钟前
1
0
MongoDB ObjectId详解及使用

MongoDB ObjectId详解及使用 2017年09月13日 14:25:18 universsky2015 阅读数:11802 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/universsky2015/article...

linjin200
35分钟前
2
0
Caffe在CentOS和Ubuntu上安装

1 CentOS上安装中需要配置第三方源 #sudo yum install epel-release 如果不安装第三方软件源,很多依赖包都不能通过yum安装 Makefile blas = open 2 Unbuntu PYTHON_INCLUDES=/usr/local/li...

shengjuntu
36分钟前
1
0
一线 IT 公司开发转管理,我是怎么从 0 到 1 的?

在某一线互联网公司的任职生涯马上就要结束了,回想起来,从 16 年校招加入,到今年年初离职,在这快三年的时间里,公司在飞速地发展和变化,我也从一个刚入职场的初级后台开发成长为带着十来...

编辑部的故事
37分钟前
1
0
Hibernate 自动建表默认编码格式改为UTF-8

Hibernate 自动建表时报编码错误: Caused by: java.sql.SQLException: Incorrect string value: '\...' for column 'cust_name' at row 1 一般情况我们使用的mysql方言为:org.hibernate.d......

gwl_
39分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部