之所以要提到global与local,是因为在开发的过程中可能会不经意的在这里踩坑。
比如说我们在开发Node项目时,经常会用到nodemon来帮助在开发期间监听文件变化并自动重启。
为了使用方便,很可能会将预定的一个启动命令放到npm scripts中去,类似这样的:
这样的项目在你本地使用是完全没有问题的,但是如果有其他的同事需要运行你的这个项目,在第一步执行npm start时就会出异常,因为他本地可能并没有安装nodemon。
以及这样的做法很可能会导致一些其它包引用的问题。
比如说,webpack实际上是支持多种语言编写config配置文件的,就拿TypeScript举例吧,最近也一直在用这个。
这样的命令是完全有效的,webpack 会使用 ts 的解释器去执行对应的配置文件
因为webpack不仅仅支持这一种解释器,有很多种,类似CoffeeScript也是支持的。
所以webpack肯定不能够将各种语言的解释器依赖都放到自身的依赖模块中去,而是会根据传入config的文件后缀名来动态的判断应该添加哪些解释器,这些在webpack的源码中很容易找到:
根据webpack动态获取解释器的模块interpret来看,.ts类型的文件会引入这些模块:['ts-node/register', 'typescript-node/register', 'typescript-register', 'typescript-require'],但是在webpack的依赖中你是找不到这些的。
在源码中也可以看到,webpack在执行config之前动态的引入了这些解释器模块。
这里也可以稍微提一下Node中引入全局模块的一些事儿,我们都知道,通过npm install安装的模块,都可以通过require('XXX')来直接引用,如果一些第三方模块需要引入某些其他的模块,那么这个模块也需要存在于它所处目录下的node_modules文件夹中才能够正确的引入。
首先有一点大家应该都知道的,目前版本的NPM,不会再有黑洞那样深的node_modules了,而是会将依赖平铺放在node_modules文件夹下。比如说你引入的模块A,A的内部引用了模块B,那么你也可以直接引用模块B,因为A和B都存在于node_modules下。
还是拿我们刚才做的那个小工具来实验,我们在fake-repo中添加express的依赖,然后在test-util中添加koa的依赖,并在test-util/index.js中require上述的两个模块。
你会发现,npx test-util运行正确,而test-util却直接报错了,提示express不存在。
我们可以通过NPM的一个命令来解释这个原因:
> npm root <current>/node_modules > npm root -g <global>/node_modules这样输出两个路径应该就能看的比较明白了,koa模块是没有问题的,因为都是存在于这些路径下的node_modules,而express则只存在于<current>/node_modules/test-util/node_modules下,全局调用下,require是找不到express的。
# global 下的结构 . ├── /usr/local/lib/node_modules # npm root 的位置 │ ├── koa │ └── test-util # 执行脚本所处的位置 └── <workspace> # 本地的项目 ├── node_modules │ └── express └── . # local 下的结构 └── <workspace> # 本地的项目 ├── node_modules # npm root 的位置 │ ├── koa │ ├── test-util # 执行脚本所处的位置 │ └── express └── .所以这也从侧面说明了为什么webpack可以直接在自己的文件中引用并不存在于自己模块下的依赖。
因为webpack认为如果你要使用TypeScript,那么一定会有对应的依赖,这个模块就是与webpack同级的依赖,也就是说webpack可以放心的进行require,大致这样的结构:
├── node_modules # npm root 的位置 │ ├── webpack │ └── typescript └── . # 在这里执行脚本以及一个相反的栗子