请停止npm install -g X行为

1,245 阅读3分钟

刚开始使用npm的时候,我并不介意全局安装npm包,甚至还享受这种「一次安装,到处使用」的快乐,同时还有许多第三方库的官方教程推荐全局安装模块,我也更加坚信这并没有什么错。但如今,我几乎不会全局安装npm包。

全局安装npm包的问题

工具与项目分离

如果运行或者构建项目的工具不是package.json的一部分,而是通过全局模块的方式安装,这会造成项目和工具的分离,从而增加开发成本。由于保证项目运行的工具并没有显式的出现在package.json的依赖中,项目管理员需要维护一套详细的文档将这「隐藏的逻辑」书写清楚。

安装负担

全局模块可以避免在各个项目中独自安装,从而避免相同模块重复安装来节约空间,从这个角度看,安装全局模块确实能带来一定的收益。但安装全局依赖和安装一个app相似,许多场景下我们用到这个模块的次数屈指可数,甚至只用一次就不再使用了,「安装全局模块」的行为也会成为一种困扰(用一次的东西,为何要花「大力气」安装后再使用)。

版本固定

全局模块安装后的版本是固定的,例如我全局安装了webpack@3,由于webpack 3webpack 4存在breaking changes, 那运行webpack@4的项目是有问题的,除非手动升级更改,这样管理上就显得很不灵活。

应该怎么做?

既然全局安装项目工具模块会引来如此多的问题,那我们应该如何操作?事实上,值得提倡的也是最简单有效的方式就是在package.jsondevDependencies列举所有的工具依赖,也就是全局向项目本地迁移。这样任何人只要执行npm install就可以获取到项目中需要的依赖模块。各个项目可以依照不同的场景管理不同的工具版本。那接下来就是调用工具模块的工作了,主要有两种方式。

npm run-scripts

package.jsonscripts定义好脚本,例如:

"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-scriptnpx来实现项目本地模块的调用,保证项目的完整统一。