60 - 《找到依赖:node 和 webpack 的 resolve 机制》
工程化小册试写章节。昨晚看 XYG 和 EStar 比赛占据太多时间,没来不及更完。。
现在基本都是模块化开发,理解「如何找到依赖」是一个很基础的知识点。但以我的接触来看,很多同学并不清楚 resolve 机制,包括很多资深的同学,然后会乱用,虽然当下能跑,但却是在给未来的自己、同事和产品留坑。
举个例子。比如一个项目,package.json 中声明 dependencies: { "foo": "1" }
,然后 foo 依赖 bar,这时开发者想用 bar 应该怎么办?
A、require('foo/node_modules/bar')
B、require('bar')
,因为用 npm 安装 foo 后,bar 被提取到 node_modules 根目录了
C、package.json 添加依赖 bar,然后 require('bar')
答案是 C。为啥 A 和 B 不行?背后原因是相同的,因为 bar 不一定出现在现在的位置。
上面的例子,通过 npm install 之后,node_modules 的结构可能是,
+ node_modules
+ foo
+ node_modules
+ bar
也可能是,
+ node_modules
+ foo
+ bar
这会受其他依赖影响,比如除了 foo 依赖 bar,项目还依赖了 B,B 也依赖了相同版本的 bar,就会是上述后者的目录结构,bar 被提取到顶层,这样设计的目的是为了避免重复。但如果又依赖了 C,C 依赖了不同版本的 bar,结构又会有变化,具体这部分我们会在 npm client 章节展开,比如典型的 Phantom dependencies 和 NPM doppelgangers 问题等。
大家可以记住一个规则,「不管是项目还是 npm 依赖,只 require 或 require.resolve 或 import 当前 package.json 的 dependencies 中声明过的依赖」。
p.s. 推荐大家用 pnpm,引用错误时会显式抛错,因为 pnpm 安装依赖后,node_modules 下只会有 package.json 中声明过的依赖。
看完例子,下面我们分 Node 的 resolve 规则和 webpack 的 reso