为中华民族的伟大复兴而读书。
上篇文章主要分享了的一个commonJS规范的问题,那么今天接着昨天的话题继续聊一聊nodejs的模块儿查找机制
在Node中引入模块,大致会经历这么几个过程:
路径分析文件定位编译执行在Node中,模块儿可以分为两大类,一类是Node提供的模块成为核心模块;另一类是用户编写的模块,成为文件模块。
核心模块在Node源码编译的过程中,编译进了二进制执行文件中。当Node进程启动时,核心模块儿会直接被加载到内存中,所以核心模块引入时,文件定位和编译执行这两个步骤可以忽略掉,并且在路径分析中会优先判断,所以核心模块的加载速度是最快的。
文件模块则是在运行中动态加载,需要完整的路径分析,文件定位,编译执行过程,加载速度比核心模块会慢一些。
优先从缓存中加载。Node对引入过的文件都会进行缓存,用来减少二次引用时的开销。与浏览器缓存不同的是,浏览器缓存的是文件,Node缓存的是编译和执行后的对象。
不论是核心模块还是文件模块,相同模块儿的二次加载都采用缓存优先的方式。但是核心模块的缓存检查优先级高于文件模块的缓存检查。
不同的标识符,模块的查找及定位也有不同程度的差异。
核心模块的优先级仅次于缓存加载,它在Node源码中已经编译成二进制代码,所以其加载速度最快。
绝对路径或相对路径这类标识符通常是我们自己写的文件模块儿,require()方法会将路径转为真实路径,并且以真实路径作为索引,将编译后的结果存放到缓存中,方便下载加载时更快。
自定义模块儿 或者可以理解为npm包。这类模块查找是最慢的,具体过程是这样的:当前目录的node_modules文件夹-->父目录下的node_modules文件夹-->递归查找父目录的node_modules-->直到根目录下的node_modules这过程跟JS的作用域链有些类似,但是文件层级越深,查找越耗时。核心模块儿如 http,fs,path...绝对路径或相对路径自定义模块儿 或者可以理解为npm包模块标识符分析文件扩展名,目录的处理,包的处理等等
默认require()方法中的标识符不带扩展名,这种情况下Node会按照.js,.json,.node的顺序依次补足扩展名,依次尝试。
这个过程中fs模块儿会同步阻塞式的判断文件是否存在。因为Node是单线程,所以会有一些性能上的问题,所以如果是json文件,带上扩展名,会多少提高一些性能。
在分析标识符的过程中,require()通过分析扩展名之后,可能没有查到对应文件,但是却得到一个目录,此时Node会将这个目录当做一个包来处理。然后查找package.json,通过JSON.parse()解析出描述对象,然后从main属性指定的文件进行定位查找。没有扩展名则补齐扩展名,如果整个过程全部走完依然没有找到目标文件,则抛出异常。文件定位下一篇简单聊一下模块如何编译及npm的相关知识点
优先从缓存加载递归查找javascript基础知识总结
本文分享自 JavaScript高级程序设计 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!