本文来自网易云社区

作者:陈观喜

网上关于npm升级很多方法多种多样,但是在windows系统下不是每种方法都会正确升级。其中在windows系统下主要的升级方法有以下三种:

  • 首先最暴力的方法删掉nodejs和npm,然后在官网上Download 最新的msi,然后msi的安装会更新你的node和npm。

  • 其次就是利用 npm install -g npm,这种方法是网上大多数人使用的方法,但是这种方法会有潜在的问题,我们在下面会介绍。

  • 最后是利用npm-windows-upgrade来升级,参见How can I update npm on Windows?用管理员权限打开PowerShell,然后执行以下命令:

    Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Forcenpm install -g npm-windows-upgradenpm-windows-upgrade

    其中,推荐使用第三种方法,这也是npm团队官方推荐使用的方法

准备工作

  1. windows下的模拟终端:推荐使用powershell,经本人测试git bash 和mintty 终端模拟器在执行npm命令的时候会有问题,这两个终端执行的原理有兴趣的可以研究一下。

三种方法的比较

1.通过升级nodejs来升级

这种方法只需要删除nodejs和npm,然后下载最新的node进行安装就行。需要注意的是,删除npm的时候,需要把NODEJS目录下的npm文件夹和APPDATA的Roaming目录下的文件夹下的npm、npm-cache文件夹删除干净。

(NODEJS目录指的是你安装nodejs的目录,默认是C:\Program Files\nodejs, APPDATA的Roaming目录指的是C:\Users\<username>\AppData\Roaming,本人的APPDATA目录是C:\Users\chenguanxi\AppData\Roaming。windows系统的应用程序经常把数据和设置存放在用户的APPDATA目录,每个windows用户都有自己的APPDATA目录。)另外,APPDATA目录的用途参考What Is the AppData Folder in Windows?

2.npm install -g npm 方法(重点介绍)

在执行这个方法之前,先看一下我现在的node和npm版本:

$ node -v
v8.11.3$ npm -v5.6.0

然后执行npm install -g npm得到以下结果:

$ npm -v 
6.4.1

好像升级成功了?!
我们来看一下是不是真的吧nodejs目录的npm升级成功了:

打开NODEJS目录下对应的npm目录(C:\Program Files\nodejs\node_modules\npm)
的package.json文件:

还是5.6.0!!

然后打开APPDATA路径下的npm目录(C:\Users\chenguanxi\AppData\Roaming\npm),可以看到这里新增加了一个npm,打开其package.json文件可以得到:

在终端下执行npm -v得到的是APPDATA目录npm的版本结果。那么在执行npm命令的时候到底是执行哪一个npm呢?

从上图得出,不管执行哪一个路径下的npm,得到的结果都是一样的。
再深一步,我们先看一下NODEJS目录下的npm是怎么执行的。打开npm.cmd文件,了解这个文件到底执行了什么。

npm命令执行原理:

我们在npm.cmd文件加上一下log看一下相关的变量:

执行npm -v得到的结果:

'~dp0: ' C:\Program Files\nodejs\'NODE_EXE: ' C:\Program Files\nodejs\\node.exe'NPM_CLI_JS: ' C:\Program Files\nodejs\\node_modules\npm\bin\npm-cli.js'NPM_PREFIX_NPM_CLI_JS: ' C:\Users\chenguanxi\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js'NPM_CLI_JS: ' C:\Users\chenguanxi\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js'npm command ===:' C:\Program Files\nodejs\\node.exe C:\Users\chenguanxi\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js6.4.1

重要的注释(具体命令参考windows批处理(cmd/bat)编程详解):

  • %~dp0只可以用在批处理文件中,它是由它所在的批处理文件的目录位置决定的,是批处理文件所在的盘符:+路径,

  • 设置npm-cli-js文件为批处理文件处理的目录对应的npm-cli.js文件关键:执行"%NODE_EXE%" "%NPM_CLI_JS%" prefix -g这个命令,也就是npm prefix -g这个命令(这个命令在下一小节说明),可以得到:C:\Users\chenguanxi\AppData\Roaming\npm。接着设置NPM_PREFIX_NPM_CLI_JS这个变量,如果存在NPM_PREFIX_NPM_CLI_JS,就把npm-cli.js设置为NPM_PREFIX_NPM_CLI_JS目录下的npm-cli.js文件

  • 最后执行node.exe {对应的}\node_modules\npm\bin\npm-cli.js

npm prefix -g这个命令得到以下结果:C:\Users\chenguanxi\AppData\Roaming\npm具体命令执行的过程大概是通过读取prefix的配置,然后输出配置的结果

  • 打开C:\Program Files\nodejs\node_modules\npm目录下的npmrc文件,可以看到只有一行的代码prefix=${APPDATA}\npm

  • ${APPDATA}指的是node环境下的process.env.APPDATA变量

  • 结果是:C:\Users\chenguanxi\AppData\Roaming

总结:

执行npm命令实际上是执行了node ${对应的}/npm-cli.js这个命令,关键是哪一个npm-cli.js文件:

  • 总的执行过程就是要判断执行哪一个npm-cli.js文件。也就是说,如果存在全局prefix,那就执行全局prefix下的那个npm-cli.js 文件

  • 也就是说执行npm命令,实际上是执行./node.exe ${对应的目录下}/node_modules\npm\bin\npm-cli.js

综上所述,npm命令执行的是nodejs目录下的npm命令。在弄清楚了npm是怎么执行之后,我们可以知道执行npm install -g npm 这个命令,其实是重新下载并安装了全局环境的npm包,然后通过prefix这个配置来链接到全局环境下的npm-cli.js文件,这个过程并没有对NODEJS目录下的npm版本进行任何修改。
所以,潜在的问题是当prefix配置被修改之后,npm执行的环境是未知的,不推荐这种通过链接到全局npm包的代理方式来升级npm。

3.npm升级的正确姿势应该是npm官方推荐的方法

参见How can I update npm on Windows?

用管理员权限打开PowerShell,然后执行以下命令:

Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Forcenpm install -g npm-windows-upgradenpm-windows-upgrade
npm-windows-upgrade的执行过程:
1.  ensureExecutionPolicy:检查用户的powershell 执行权限政策等2.  ensureInternet:检查用户的网络状况3.  chooseVersion: 让用户选择一个npm版本4.  choosePath: 找到正确的npm安装目录5.  upgrade:自动找到正升级npm的正确目录,保护和重新应用现有的配置,最终调用npm install -g npm

详细过程有兴趣的可以打开源文件看一下:
主要是以下三个文件:

  1. C:\Users\chenguanxi\AppData\Roaming\npm\npm-windows-upgrade.cmd

  2. C:\Users\chenguanxi\AppData\Roaming\npm\node_modules\npm-windows-upgrade\bin\npm-windows-upgrade.js

  3. C:\Users\chenguanxi\AppData\Roaming\npm\node_modules\npm-windows-upgrade\lib\upgrader.js

也就是说执行npm-windows-upgrade,它会帮助我们自动找到正升级npm的正确目录,保护和重新应用现有的配置,最终调用npm install -g npm

总结

综上,在windows系统下升级npm的最佳方法是用npm-windows-upgrade来升级,这样可以保护并且重新应用到现有的配置,避免了潜在的问题。
通过以上实验过程有以下知识点总结:

  • npm命令是通过node npm-cli.js 命令来实现的

  • windows系统下,npm的全局包管理环境和node目录是分开的

以上有不对的地方,希望大家指正。

参考:

网易云免费体验馆,0成本体验20+款云产品!

更多网易研发、产品、运营经验分享请访问网易云社区

相关文章:
【推荐】 SpringBoot入门(四)——自动配置
【推荐】 从细节处谈Android冷启动优化
【推荐】 网易云复盘:云计算前端这一年(AngularJS粉慎入)

windows系统下npm升级的正确姿势以及原理的更多相关文章

  1. windows系统下npm 全局安装路径问题

    安装了nodejs之后,npm的路径默认一直都是appData,表示很讨厌,于是尝试修改在安装目录(D盘空间很大啊) 安装目录:D:\program files\nodejs 一.在nodejs下新建 ...

  2. 如何正确入门Windows系统下驱动开发领域?

    [作者]猪头三个人网站 :http://www.x86asm.com/ [序言]很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都以英文 ...

  3. windows系统下如何正确安装Cygwin(图文详解)

    我的操作系统信息是 1.在官网https://cygwin.com/install.html下载win64位安装包 选择包的下载存放目录,点击“下一步”   为了使我们安装的Cygwin能够编译程序, ...

  4. [记]Windows 系统下设置Nodejs NPM全局路径

    Windows下的Nodejs npm路径是appdata,担心安装的node_modules越来越多,导致C盘满,所以参考别人的博文,将node_modules安装的默认目录修改一下. 参考Wind ...

  5. windows系统下简单nodejs安装及环境配置

      相信对于很多关注javascript发展的同学来说,nodejs已经不是一个陌生的词眼,这里不想谈太多的nodejs的相关信息.只说一下,windows系统下简单nodejs环境配置     相信 ...

  6. 如何用python在Windows系统下,生成UNIX格式文件

    平时测试工作中,少不了制造测试数据.最近一个项目,我就需要制造一批可在UNIX下正确读取的文件.为确保这批文件能从FTP下载成功,开发叮嘱我:“文件中凡是遇到换行,换行符必须是UNIX下的LF,而不是 ...

  7. Windows环境下npm install常见错误

    Windows环境下npm install安装包依赖时,常出现一些错误,下面为个人解决办法: 错误一 缺少python环境: G:\nodejs\moviesite\node_modules\bcry ...

  8. windows系统下简单nodej.s环境配置 安装

    国内目前关注最高,维护最好的一个关于nodejs的网站应该是http://www.cnodejs.org/ windows系统下简单nodejs环境配置. 第一步:下载安装文件 下载地址:官网 htt ...

  9. windows系统下安装MySQL

    可以运行在本地windows版本的MySQL数据库程 序自从3.21版以后已经可以从MySQL AB公司获得,而且 MYSQL每日的下载百分比非常大.这部分描述在windows上安装MySQL的过程. ...

随机推荐

  1. [BJWC2008]秦腾与教学评估

    嘟嘟嘟 二分好题. 怎么二分呢?反正我是没想出来. 看了题解. 因为只有一个为奇数的点,所以对于一个位置x,求出区间[0, x]的教总和,如果为奇数,说明x取大了:否则x取小了(妙啊). 虽然答案在i ...

  2. 【JeeSite】区域和菜单管理

    /** * 区域Entity * @author ThinkGem * @version 2013-05-15 */ public class Area extends TreeEntity<A ...

  3. vue案列

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. android jni 之C语言基础

    *含义 1.乘法 3*5 2.定义指针变量 int * p://定义了一个名字叫p的变量,能够存放int数据类型的地址 3.指针运算符, //如果p是一个已经定义好的指针变量则*p表示以p的内容为地址 ...

  5. HDU 1175 连连看(超级经典的bfs之一)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1175 连连看 Time Limit: 20000/10000 MS (Java/Others)     ...

  6. PL/SQL规范、块、过程、函数、包、触发器

    1.pl/sql规范 标识符号的命名规范 1) 定义变量,用 v- 作为前缀 v-sal 2)定义常亮, 用 c- 作为前缀 c-rate 3) 定义游标,用 cursor作为后缀 emp_curso ...

  7. deep learning学习记录三

    deep learning,这几年有多火!! imagenet比赛,大家今年都是基于去年的基础上改进和应用的,效果比去年提升当然. 在deep learning方向,hinton, benjio, l ...

  8. windows下搭建python

    windows下搭建python 下载python版本  https://www.python.org/   注意当前操作系统的位数,32位还是64位 同时   安装后  修改环境变量         ...

  9. IPv6静态路由、动态路由

    实验涉及命令以及知识补充 IPv6 接口必须配置 IPv6 地址和子网掩码 使用 ipv6 address ipv6-address/prefix-length [link-local | eui-6 ...

  10. 并发编程之多线程基础-Thread和Runnable的区别及联系(二)

    上篇文章讲述了创建线程的常用方式 本篇主要分析一下Thread和Runnable两种方式创建线程的区别及联系 联系: ▶Thread类实现了Runable接口. ▶都需要重写里面Run方法. 区别: ...