刚开始使用npm
的时候,我并不介意全局安装npm
包,甚至还享受这种「一次安装,到处使用」的快乐,同时还有许多第三方库的官方教程推荐全局安装模块,我也更加坚信这并没有什么错。但如今,我几乎不会全局安装npm
包。
全局安装npm包的问题
工具与项目分离
如果运行或者构建项目的工具不是package.json
的一部分,而是通过全局模块的方式安装,这会造成项目和工具的分离,从而增加开发成本。由于保证项目运行的工具并没有显式的出现在package.json
的依赖中,项目管理员需要维护一套详细的文档将这「隐藏的逻辑」书写清楚。
安装负担
全局模块可以避免在各个项目中独自安装,从而避免相同模块重复安装来节约空间,从这个角度看,安装全局模块确实能带来一定的收益。但安装全局依赖和安装一个app
相似,许多场景下我们用到这个模块的次数屈指可数,甚至只用一次就不再使用了,「安装全局模块」的行为也会成为一种困扰(用一次的东西,为何要花「大力气」安装后再使用)。
版本固定
全局模块安装后的版本是固定的,例如我全局安装了webpack@3
,由于webpack 3
与webpack 4
存在breaking changes
, 那运行webpack@4
的项目是有问题的,除非手动升级更改,这样管理上就显得很不灵活。
应该怎么做?
既然全局安装项目工具模块会引来如此多的问题,那我们应该如何操作?事实上,值得提倡的也是最简单有效的方式就是在package.json
的devDependencies
列举所有的工具依赖,也就是全局向项目本地迁移。这样任何人只要执行npm install
就可以获取到项目中需要的依赖模块。各个项目可以依照不同的场景管理不同的工具版本。那接下来就是调用工具模块的工作了,主要有两种方式。
npm run-scripts
package.json
的scripts
定义好脚本,例如:
"scripts": {
"build": "webpack --mode=production --config ./webpack.config.js",
},
复制代码
npm run-scripts
会执行node_modules/.bin
下对应的二进制文件,只要成功install
了模块,就可以像调用全局模块一样在npm run-scripts
中调用项目本地模块。
npx
npm@5.2.0
版本后自带了另一个工具npx,它是为替代全局安装模块推出的。此前使用全局模块方式创建react template
的过程是:
npm install -g create-react-app
create-react-app my-app
复制代码
使用npx
则会是这样(create-react-app目前已推荐使用npx
安装):
npx create-react-app my-app
复制代码
npx
主要有以下几个特点:
- 寻找当前目录下的
node_modules
是否存在对应模块,存在则直接执行,不存在则自动安装模块后执行 - 执行完毕后清除模块(不会清除项目本地
node_modules
下的模块),避免造成全局模块污染
如此看来,npx
并不会造成任何负担,做到了即用即走
。
总结
全局模块会带来诸多项目开发和管理的问题,可以使用devDependencies + npm run-script
或npx
来实现项目本地模块的调用,保证项目的完整统一。