nodejs包依赖管理

鲜花总需要绿叶衬托的,对比PHP,java,python的包依赖管理,顿时觉得nodejs包依赖机制真是漂亮。此文不吐槽python的包管理是如何难用和混乱,也不去抨击PHP包管理的孱弱,仅仅讨论如何优雅地使用npm进行包依赖管理。

告别npm2.x,拥抱 npm3.x+

升级到3.x执行以下命令:

npm install -g npm@3

先上图

图中A和C都依赖了B,但是A依赖的是B v1.0,但是C依赖的是B v2.0,在npm2里面直接就是把B的分别放在A的node_modules文件夹里面,而npm3的处理方式是把B v1.0抽离出来作为一个单独的模块,而C所依赖的B v2.0则单独放到C中。
在实际项目中,npm2会产生了大量冗余的引用,node_modules也会很大,npm3把结构扁平化了,实际上项目依赖的版本已经十分一致,像C单独依赖Bv2.0这种情况不多,所以npm3处理的node_modules体积小,效率更高。而且npm3.x是兼容npm2.x的,并无后顾之忧。

深入可以阅读文档:http://www.alloyteam.com/2016...

注意版本号的控制方式

打开package.json这个文件,往往会看到dependencies中定义了一大堆的依赖,形式一般有以下几种:

*: 任意版本
1.1.0: 指定版本
~1.1.0: >=1.1.0 && < 1.2.0
^1.1.0: >=1.1.0 && < 2.0.0

上面的规则已经很清晰地表述了各种符号代表的意思。
那么我们回到使用场景中,什么时候我们会锁定版本,什么时候会用~,什么时候会用^?
我的理解如下:
(1)如果对依赖的包的稳定性要求极高,不希望有任何的更新,那么就要锁定版本。
1.1 项目中核心的包建议都锁住某一稳定版本,例如react的项目中,react的版本就应该被锁定。没有经过完整的测试之前,不能随意升级版本,即使是小版本升级也不允许。
1.2 如果明知道包的开发者不稳定,经常会更新一下不稳定的版本,那么也需要锁住版本,例如antd;
(2) 如果希望依赖包在小幅范围内升级,并且确信不会影响稳定性,又能得益更新带来的好处,那么可以用~符号
(3) 如果对包的稳定性要求不高,确信不是大版本更新都不会影响稳定性,那么久可以用^符号,不过要慎重;
开源项目一般都使用~或者^符号来管理版本

感兴趣的同学可以阅读以下文档:
论版本号的正确打开方式:http://taobaofed.org/blog/201...

注意从npm2升级到npm3需要删除旧的node_modules文件

尽管npm3会兼容npm2,但是历史遗留问题往往让人防不胜防,最好的方式莫过于抹去旧的,放进新的。就譬如,昨天晚上留下了茶水,今天再把新泡的茶冲进去,味道也没有新茶好,甚至会拉肚子。

上面的文字已经阐述了npm2和npm3的机制,看起来是没有问题的,请注意C中引用Bv2,是把B v2放在C的node_modules文件夹中,新旧切换时就要考虑npm引用包的顺序,如果一个包下面有node_modules文件夹,npm会优先查找node_modules里面的包,然后再到外层,最后到全局。这是时候npm2的残留是那么顽固,因为它是把依赖放在自己node_modules文件夹下面的。对此,别无更好的办法,除非删掉,重新install。因此在发布和构建是一定要注意npm的版本,要考虑2到3切换时可能带来的风险。笔者已经吃过这方面的亏了。

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...