npx 命令 - 不仅仅是 command 寻址
前言
npx 出现的次数还是比较多,像 Vite、Expo、React Native 的文档都有介绍它相关的用法,比如
# Vite
npx degit user/project my-project
# Expo
npx create-expo-app my-app
# React Native
npx create-expo-app AwesomeProject
我一开始接触到 npx 还是在运行 express(一个 node.js 后端框架)时想要热更新,当时用的是 supervisor,结果我当时弄半天没有运行,后来去的思否提问才得到答案,可以使用 npx,原理是找到 node_modules/.bin 里面的 shell 可执行文件
但是 npx 只是寻址这么简单吗?
npx
在 npm 的文档里,npx 被定义为
从本地或远程 npm 包运行命令
首先就是了解一下 npm 包运行命令是啥?有些 npm 包它是提供有 CLI(命令行接口)的,比如 supervisor、prettier、webpack,安装完包之后可以在 node_modules/.bin 这个目录下找到对应的执行文件,而使用上可以通过 package.json 里面的 script 属性配置命令

比如
// package.json
{
// ...
"scripts": {
"version": "webpack -v"
},
// ...
}
使用 npm run version 就可以打印出当前项目的 Webpack 的正确版本,又或者可以使用
# Windows
node_modules\.bin\webpack -v
本质上就是运行包自带的可执行文件(学过 Linux 的对于这些知识应该都是洒洒水了)
而除了上面这两种方法以外,文章的主角 npx 也可以达到同样作用,而且是兼容的
// package.json
{
// ...
"scripts": {
"version": "npx webpack -v"
},
// ...
}
// 等同于 shell 下
// $ npx webpack -v
关于 npx 和 npm(主要指的是 npm-run-script)的区别已经有很多文章介绍过了,比如[npm 和 npx 有什么区别?](npm 和 npx 有什么区别? - 知乎 www.zhihu.com/question/32…)
但除了这个,npx 还有其它的功能
避免全局安装
npx 在执行时,如果发现本地项目依赖项中不存在的包,则会自行安装远程 npm 库中的包至 npm 缓存当中,运行完成后会删除,比如
# Expo
npx create-expo-app my-app
为什么需要去避免全局安装呢?因为 node.js 会将其全局的 .bin 放到环境变量里面,所以全局安装的包的执行命令可能会和你本地的其它环境变量有冲突
比如 Java 的 Yarn 和 NodeJs 的 Yarn
选择版本运行
对于 npx 运行的包命令,可以自行选择包的版本
npx -- <pkg>[@<version>] [args...]
这个特性就很有意思,可以去验证不同的包它版本之间的差异,比如
npx -- rollup@3.7.2 -v # 3.7.2
npx -- rollup@3.8.0 -v # 3.8.0
实测 npm@8.11.0 的全局是不能有这个包的,否则会运行全局包对应的命令
切换 NodeJS 版本
npx 还可以用来测试不同 NodeJS 版本环境下的脚本运行效果,比如
npx node@10.4.0 -v # 10.4.0
// t.js
console.log(Promise);
npx node@0.2.0 t.js
# 报错如下
# npm ERR! code ETARGET
# npm ERR! notarget No matching version found for node-win-x64@0.2.0
# npm ERR! notarget In most cases you or one of your dependencies are requesting
# ...
# module.js:538
# throw err;
# ^
# Error: Cannot find module 'node-win-x64/package.json'
# ...
# Install for node@0.2.0 failed with code 1
而对于 node@10.4.0 则会输出如下
npx node@10.4.0 t.js
# null
# function
注意,对于选择版本运行章节内容
测试环境 npm@5.5.1 + node@8.9.0 能够成功运行,而在 npm@8.11.0 + node@16.15.1 却失去预期(即不能正确执行 shell 脚本),留坑后期解惑后重新更新
转载自:https://juejin.cn/post/7180744618403692599