npm 为什么优先安装到当前项目目录?
优点
- 项目中的 .npmrc
项目下 .npmrc 文件的优先级最高,可以给每个项目配置不同的镜像,项目之间的配置互不影响。
在项目的根目录下新建 .npmrc 文件,在里面以 key=value 的格式进行配置。
registry=https://registry.npm.taobao.org
- 用户配置的 .npmrc(~/.npmrc)
可以通过npm config get userconfig
命令获取用户配置的 .npmrc 文件在哪里。
可以通过npm config set
命令设置用户级别的 .npmrc 配置。
npm config set registry https://registry.npm.taobao.org
如果想删除可以直接编辑文件,或者使用npm config delete registry
命令来进行删除。
- 全局配置的 .npmrc
可以通过 npm config get prefix
命令获取全局配置的 .npmrc 文件的前缀地址,
记住是前缀地址,不是完整地址。完整地址是{$prefix}/etc/npmrc
。
但是如果你从来没有全局配置过,就不会存在这个文件。
也可以通过命令行来进行全局 .npmrc 文件的配置。
npm config set registry https://registry.npm.taobao.org -g
- npm 内置的 .npmrc
npm 内置 .npmrc 配置文件和 npm 同级,所以可以通过获取 npm 的路径,来找到 npm 内置的 .npmrc 文件。
可以通过 which npm
来获取npm 的路径,也就找到了npm 内置的 .npmrc 文件。
npm install 执行之后,首先,检查并获取 npm 配置,这里的优先级为:项目级的 .npmrc 文件 > 用户级的 .npmrc 文件> 全局级的 .npmrc 文件 > npm 内置的 .npmrc 文件。
构建依赖树
当前依赖项目不管其是直接依赖
还是子依赖的依赖
,都应该按照扁平化原则
,优先将其放置在 node_modules 根目录(最新版本 npm 规范)。
在这个过程中,遇到相同模块就判断已放置在依赖树中的模块版本是否符合新模块的版本范围,如果符合则跳过;不符合则在当前模块的 node_modules 下放置该模块(最新版本 npm 规范)。
npm 缓存机制
通过 npm config get cache
命令可以获取到缓存配置的路径。
打开缓存路径目录,在缓存目录下,存在一个很重要的目录,那就是_cacache
目录,这个目录就是存在的缓存数据,在 npm v5 版本之后缓存都是存储在 _cacache
目录下。_cacache
目录下有两个目录比较重要,是缓存的关键。
- content-v2
- index-v5
content-v2
下面有很多目录,
我们随机找到一个文件,打开看看是什么。
发现是乱码,这里就需要用一个小技巧,把这些乱码解析出来。我们将乱码的文件改成压缩文件,文件扩展名改成 .tgz,然后在解压,得到的结果是 npm 包的资源。也就是说,在**content-v2**
目录下存放的就是 npm 包的缓存资源。
我们再来看看 index-v5
目录下存在的是什么?我们也随机打开一个文件,看看是什么?
文件里面有 hash 还有一些相关的信息,其实这些所有的内容构成了**content-v2**
目录下 npm 包资源的引索。
有了缓存的 npm 包资源,也有了包资源的引索信息,那如何将缓存的资源加载到我们的项目中的了?
注意,这里提到的缓存策略是从 npm v5 版本开始的。在 npm v5 版本之前,每个缓存的模块在 ~/.npm 文件夹中以模块名的形式直接存储,储存结构是:{cache}/{name}/{version}。
npm 离线安装
- —prefer-offline:优先使用缓存数据,如果没有匹配的缓存数据,则从远程仓库下载。
- —prefeer-online:优先使用网络数据,忽略缓存数据。
- —offline:完全使用缓存数据,如果缓存中不存在,就按照失败。
npm 不完全指南
自定义 npm init
npm 支持我们自定义 npm init,快速创建一个符合自己需求的自定义项目。npm init 命令本身并不复杂,它其实就是调用 shell 脚本输出一个初始化的 package.json 文件。那么相应地,我们要自定义 npm init 命令,就是写一个 node 脚本而已,它的 module.exports 即为 package.json 配置内容。 ```javascript const { exec } = require(‘child_process’);
const desc = prompt(‘请输入项目描述’, ‘项目描述…’);
module.exports = {
key: ‘value’,
name: prompt(‘name?’, process.cwd().split(‘/‘).pop()),
version: prompt(‘version?’, ‘0.0.1’),
description: desc,
main: ‘index.js’,
repository: prompt(‘github repository url’, ‘’, function (url) {
if (url) {
exec(‘touch README.md’);
exec(‘git init’);
exec(git remote add origin ${url}
);
exec(‘git add .’);
exec(‘git commit -m “first commit”‘);
exec(‘git push -u origin master’);
}
return url;
}),
};
``
使用命令
npm config set init-module ~.npm-init.js来设置当我们执行
npm init`时可以执行我们自定义的脚本。
利用 npm link,高效率在本地调试以验证包的可用性
npm link
可以将模块链接到对应的业务项目中运行。